基于ruoyi-vue框架,新增一个简单的系统通用文件模块,服务与各个模块涉及到文件上传信息的记录和相关展示
运行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来区分不同的模块。
@PostMapping(value = "/uploadFile")@ResponseBodypublic 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 补充以下代码。
/*** 系统文件* @return*/
public static String getUploadSysFilePath()
{return getProfile() + "/sysFile";
}
3、FileUtils.getFileSize()爆红,在FileUtils.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、将原来的批量删除、和删除方法调整如下,实现先删除文件,再删除数据信息
/*** 批量删除系统通用文件库* * @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、组件引入
<el-form-item label="附件"><el-uploadclass="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
import { getToken } from "@/utils/auth";
3、引入api
import { listFileInfo,delFileInfo} from "@/api/system/fileInfo";
4、data中添加属性
upload: {// 是否禁用上传isUploading: false,// 设置上传的请求头部headers: { Authorization: "Bearer " + getToken() },// 上传的地址(接口就是上文的文件上传接口)url: process.env.VUE_APP_BASE_API + "/system/fileInfo/uploadFile",// 上传的文件列表fileList: [],//携带参数data: {linkObjId: null,type: 1,}
},
5、添加对应事件
//文件提交处理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
/** 提交按钮 */ 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会自增:
@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赋值请求到的文件列表信息就行
//查看
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.sysFileInfoListthis.seeOpen = true;this.title = "查看授权申请单";});
},
8、文件列表重置,不然会有缓存问题
在this.reset()方法里加上this.upload.fileList=[]
注意事项
1、会使用若依分离版的代码生成功能
2、注意接口是否对应得上