【VUE_ruoyi-vue】基于ruoyi-vue框架实现简单的系统通用文件模块

基于ruoyi-vue框架,新增一个简单的系统通用文件模块,服务与各个模块涉及到文件上传信息的记录和相关展示

运行sql,创建数据库表

sql 复制代码
DROP TABLE IF EXISTS `sys_file_info`;
CREATE TABLE `sys_file_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `link_obj_id` int(11) DEFAULT NULL COMMENT '关联对象id',
  `name` varchar(255) DEFAULT NULL COMMENT '文件名称',
  `file_type` varchar(255) DEFAULT NULL COMMENT '文件类型',
  `type` char(10) DEFAULT NULL COMMENT '归属类型(预留字段,比如归属某个模块)',
  `file_size` varchar(255) DEFAULT NULL COMMENT '文件大小',
  `file_path` varchar(255) DEFAULT NULL COMMENT '文件路径',
  `create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `i_pof_type` (`link_obj_id`,`type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='系统通用文件库';

生成代码

(按正常的若依分离版生成导入代码流程走)在系统工具生成代码,然后再编辑代码生成的内容,调整一下业务名,看自己的需求吧。

将生成后的后端代码加入系统模块相关位置,生成的前端代码内容如果不做台账管理则只用生成的api接口文件就行,后续要用到文件删除和请求。如果需要做台账则同样加到前端相应模块下,然后运行生成的sql文件(主要是生成相关路由菜单信息)即可,其他不多赘述。

java部分

1、在文件模块的controller层补充文件上传接口,代码如下:

重点:String linkObjId = map.get("linkObjId"); String type = map.get("type"); 获取前端组件额外传的参数,分别对应相关模块的数据id和模块类型,因为现在采用的id是1开始递增,不是全系统唯一uuid,因此可能不同模块会出现相同id,导致文件数据绑定异常,需要加上type来区分不同的模块。

java 复制代码
    @PostMapping(value = "/uploadFile")
    @ResponseBody
    public AjaxResult uploadFile(SysFileInfo pdFile, MultipartFile[] file, @RequestParam Map<String,String> map) {
        String linkObjId = map.get("linkObjId");
        String type = map.get("type");
        try {
            System.out.println("文件上传进入方法!");
            List<SysFileInfo> list = new ArrayList<SysFileInfo>();
            for (MultipartFile f : file) {
                // 文件保存路径
                String loadPath = FileUploadUtils.upload(RuoYiConfig.getUploadSysFilePath(), f);
                pdFile.setFilePath(loadPath);
                // 保存文件名
                String f_name = f.getOriginalFilename();
                pdFile.setName(f_name);
                pdFile.setLinkObjId(Long.valueOf(linkObjId));
                pdFile.setType(type);
                pdFile.setFileSize(
                        FileUtils.getFileSize(RuoYiConfig.getProfile() + loadPath.replace(Constants.RESOURCE_PREFIX, ""))
                                + " kb");
                sysFileInfoService.insertSysFileInfo(pdFile);
                list.add(pdFile);
            }
            return AjaxResult.success(list);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("文件上传失败!" + e.getMessage());
        }
    }

2、RuoYiConfig.getUploadSysFilePath()爆红,为了和原来自带的上传路径(原来的是getUploadPath,按自己的需求调整,用原来的也行)做个区分,需要处理文件上传存储位置,在RuoYiConfig.java 补充以下代码。

java 复制代码
/**
 * 系统文件
 * @return
 */
public static String getUploadSysFilePath()
{
    return getProfile() + "/sysFile";
}

3、FileUtils.getFileSize()爆红,在FileUtils.java补充获取文件大小的方法, 没有这个需求就不用处理

java 复制代码
/**
 * 计算文件大小
 * @param  filePath
 * @return 单位是byte
 */
public static long getFileSize(String filePath) {
    long size = 0;
    FileInputStream fis= null;
    FileChannel fc= null;
    try {
        File f = new File(filePath);
        if (f.exists() && f.isFile()){
            fis= new FileInputStream(f);
            fc= fis.getChannel();
            size = fc.size();
        }else{
            // Constant.LOGGER.error("{},file doesn't exist or is not a file", filePath);
        }
    } catch (FileNotFoundException e) {
        //Constant.LOGGER.error("文件大小检查发生异常,{}", e.getMessage());
        e.getMessage();
    } catch (IOException e) {
        // Constant.LOGGER.error("文件大小检查发生异常,{}", e.getMessage());
        e.getMessage();
    } finally {
        if (null!=fc){
            try{
                fc.close();
            }catch(IOException e){
                e.getMessage();
            }
        }
        if (null!=fis){
            try{
                fis.close();
            }catch(IOException e){
                // Constant.LOGGER.error("FileInputStream资源关闭发生异常,{}", e.getMessage());
                e.getMessage();
            }
        }
    }
    return size/1024;
}

4、将原来的批量删除、和删除方法调整如下,实现先删除文件,再删除数据信息

java 复制代码
/**
 * 批量删除系统通用文件库
 * 
 * @param ids 需要删除的系统通用文件库主键
 * @return 结果
 */
@Override
public int deleteSysFileInfoByIds(Long[] ids)
{
    for(Long id :ids){
        SysFileInfo sysFiles = selectSysFileInfoById(id);
        String path= RuoYiConfig.getProfile() + sysFiles.getFilePath().replace(Constants.RESOURCE_PREFIX, "");
        FileUtils.deleteFile(path);
    }
    return sysFileInfoMapper.deleteSysFileInfoByIds(ids);
}

/**
 * 删除系统通用文件库信息
 * 
 * @param id 系统通用文件库主键
 * @return 结果
 */
@Override
public int deleteSysFileInfoById(Long id)
{
    //删除本地文件
    SysFileInfo sysFiles = selectSysFileInfoById(id);
    String path= RuoYiConfig.getProfile() + sysFiles.getFilePath().replace(Constants.RESOURCE_PREFIX, "");
    FileUtils.deleteFile(path);
    // 删除数据库文件记录
    return sysFileInfoMapper.deleteSysFileInfoById(id);
}

其他爆红导入相关类就行。

前端在需要文件上传的地方处理文件上传

1、组件引入

java 复制代码
<el-form-item label="附件">
	<el-upload
	  class="notice_upload"
	  ref="upload"
	  :limit="7"
	  accept=""
	  multiple
	  :data="upload.data"
	  :headers="upload.headers"
	  :action="upload.url"
	  :disabled="upload.isUploading"
	  :on-progress="handleFileUploadProgress"
	  :on-success="handleFileSuccess"
	  :on-preview="handleDownload"
	  :show-file-list="true"
	  :file-list="upload.fileList"
	  :auto-upload="false"
	  :before-remove="beforeRemove"
	  :on-remove="handleRemove"
	>
	  <em v-if="!upload.isUploading">
	    <div
	      :style="{
	        width: '80px',
	        height: '30px',
	        lineHeight: '20px',
	        color: theme,
	      }"
	    >
	      <i class="el-icon-link"></i> 点击上传
	    </div>
	  </em>
	</el-upload>
</el-form-item>

2、引入获取token

java 复制代码
import { getToken } from "@/utils/auth";

3、引入api

java 复制代码
import { listFileInfo,delFileInfo} from "@/api/system/fileInfo";

4、data中添加属性

java 复制代码
upload: {
  // 是否禁用上传
  isUploading: false,
  // 设置上传的请求头部
  headers: { Authorization: "Bearer " + getToken() },
  // 上传的地址(接口就是上文的文件上传接口)
  url: process.env.VUE_APP_BASE_API + "/system/fileInfo/uploadFile",
  // 上传的文件列表
  fileList: [],
  //携带参数
  data: {
    linkObjId: null,
    type: 1,
  }
},

5、添加对应事件

java 复制代码
   //文件提交处理
	submitUpload() {
	  this.$refs.upload.submit();
	},
	// 文件上传中处理
	handleFileUploadProgress(event, file, fileList) {
	  this.upload.isUploading = true;
	},
	// 文件上传成功处理
	handleFileSuccess(response, file, fileList) {
	  this.upload.isUploading = false;
	},
	// 删除文件之前确认
	beforeRemove(file, fileList) {
	    return this.$confirm(`是否确定永久移除文件 ${file.name}?`);
	},
	//文件删除
	handleRemove(file, fileList) {
	  if (file.id) {
	    delFileInfo(file.id)
	      .then((res) => {
	        this.$message.success(res.msg);
	        console.log("res", res);
	      })
	      .catch((err) => {
	        this.$message.errer(err + "");
	        console.log("err", err);
	      });
	  }
	},
	// 文件下载处理
	handleDownload(file) {
	 var name = file.name;
	 //先打印看文件信息再调整url构建
	 var url = process.env.VUE_APP_BASE_API + file.filePath;
	 const a = document.createElement("a");
	 a.setAttribute("download", name);
	 a.setAttribute("target", "_blank");
	 a.setAttribute("href", url);
	 a.click();
	},

6、在表单提交时,调用文件上传方法,注意id的获取,this.upload.data.linkObjId

java 复制代码
  /** 提交按钮 */ 			
  submitForm(e) {
	this.$refs["form"].validate((valid) => {
		if (valid) {
			if (this.form.id != null) {
				updateWorkInfo(this.form).then((response) => {
					console.log("修改:" + response)
					this.$modal.msgSuccess("修改成功");
					this.upload.data.linkObjId=this.form.id;
					this.submitUpload()
					this.open = false;
					this.$emit("cancel")
				});
			} else {
				addWorkInfo(this.form).then((response) => {
					this.$modal.msgSuccess("新增成功");
					this.upload.data.linkObjId=response.id;
					this.submitUpload()
					this.open = false;
					this.$emit("cancel")
				});
			}
		}
	}); 			
},

补充,后端处理新增返回id的方式,需求表单的id会自增:

java 复制代码
@PostMapping
public AjaxResult add(@RequestBody WorkInfo workInfo ) {
    workInfoService.insertWorkInfo (workInfo);
    AjaxResult ajaxResult = new AjaxResult();
    ajaxResult.put("id",workInfo.getId());
    return ajaxResult;
}

7、附件回显,再点击修改或者查看事件的方法内给this.upload.fileList赋值请求到的文件列表信息就行

java 复制代码
//查看
handleView(row) {
	this.reset();
	const id = row.id || this.ids;
	getWorkInfo(id).then((response) => {
		this.form = response.data;
		//处理文件信息(可以在后端WorkInfo加个返回参数,也可以在这里请求文件信息数据再赋值,注意type和linkObjId的参数传值)
		this.upload.fileList=response.data.sysFileInfoList
		this.seeOpen = true;
		this.title = "查看授权申请单";
	});
},

8、文件列表重置,不然会有缓存问题

在this.reset()方法里加上this.upload.fileList=[]

注意事项

1、会使用若依分离版的代码生成功能

2、注意接口是否对应得上

相关推荐
寻找沙漠的人10 分钟前
前端知识补充—CSS
前端·css
GISer_Jing21 分钟前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_7482455223 分钟前
吉利前端、AI面试
前端·面试·职场和发展
理想不理想v35 分钟前
webpack最基础的配置
前端·webpack·node.js
pubuzhixing38 分钟前
开源白板新方案:Plait 同时支持 Angular 和 React 啦!
前端·开源·github
2401_857600951 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_857600951 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL1 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
小白学大数据1 小时前
如何使用Selenium处理JavaScript动态加载的内容?
大数据·javascript·爬虫·selenium·测试工具
轻口味1 小时前
Vue.js 核心概念:模板、指令、数据绑定
vue.js