package com.artfess.file.controller; import com.artfess.base.annotation.ApiGroup; import com.artfess.base.constants.ApiGroupConsts; import com.artfess.base.context.BaseContext; import com.artfess.base.controller.BaseController; import com.artfess.base.exception.NotFoundException; import com.artfess.base.feign.UCFeignService; import com.artfess.base.feign.WorkflowFeignService; import com.artfess.base.groovy.GroovyScriptEngine; import com.artfess.base.handler.MultiTenantHandler; import com.artfess.base.handler.MultiTenantIgnoreResult; import com.artfess.base.model.CommonResult; import com.artfess.base.query.PageList; import com.artfess.base.query.QueryField; import com.artfess.base.query.QueryFilter; import com.artfess.base.query.QueryOP; import com.artfess.base.util.Base64; import com.artfess.base.util.BeanUtils; import com.artfess.base.util.FileUtil; import com.artfess.base.util.JsonUtil; import com.artfess.base.util.StringUtil; import com.artfess.base.util.UniqueIdUtil; import com.artfess.base.util.time.DateUtil; import com.artfess.file.config.UploadResult; import com.artfess.file.extend.DetailTablePolicy; import com.artfess.file.extend.InstanceFlowOpinions; import com.artfess.file.model.DefaultFile; import com.artfess.file.model.FileZone; import com.artfess.file.persistence.manager.CatalogManager; import com.artfess.file.persistence.manager.FileManager; import com.artfess.file.persistence.manager.FileZoneManager; import com.artfess.file.util.AppFileUtil; import com.artfess.file.util.HtmlUtil; import com.artfess.file.util.SignaturePictureRenderPolicy; import com.artfess.file.vo.FileReqVo; import com.artfess.sysConfig.util.SysPropertyUtil; import com.artfess.uc.api.model.IUser; import com.artfess.uc.api.service.IUserService; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.deepoove.poi.config.Configure.ELMode; import com.deepoove.poi.data.DocxRenderData; import com.deepoove.poi.template.MetaTemplate; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import javax.activation.MimetypesFileTypeMap; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.net.URLEncoder; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; @RestController @RequestMapping("/file/v1") @Api(tags = "附件管理") @ApiGroup(group = { ApiGroupConsts.GROUP_SYSTEM }) @SuppressWarnings({ "unchecked", "rawtypes" }) public class FileController extends BaseController { private Logger logger = LoggerFactory.getLogger(FileController.class); @Resource FileManager fileManager; @Resource IUserService userService; @Resource CatalogManager catalogManager; @Resource FileZoneManager fileZonedManager; @Resource BaseContext baseContext; @Resource WorkflowFeignService workflowFeignService; @Resource GroovyScriptEngine groovyScriptEngine; @Resource UCFeignService ucFeignService; @RequestMapping(value = "list", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "附件列表(分页条件查询)数据", httpMethod = "POST", notes = "附件列表(分页条件查询)数据") public PageList list( @ApiParam(name = "queryFilter", value = "通用查询对象") @RequestBody QueryFilter queryFilter) { List listQueryField = queryFilter.getQuerys(); List listId = new ArrayList<>(); QueryField query = new QueryField(); String xbTypeId = ""; for (QueryField queryField : listQueryField) { if ("xbTypeId".equals(queryField.getProperty())) { xbTypeId = queryField.getValue() + ""; query.setProperty(queryField.getProperty()); query.setRelation(queryField.getRelation()); listQueryField.remove(queryField); break; } } if (StringUtil.isNotEmpty(xbTypeId)) { List ids = catalogManager.getDepartmentList(xbTypeId, listId); ids.add(xbTypeId); query.setValue(ids); query.setOperation(QueryOP.IN); listQueryField.add(query); queryFilter.setQuerys(listQueryField); } return fileManager.query(queryFilter); } @PostMapping(value = "getFileInfo", produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "根据附件类型和业务id获得附件对象", notes = "获得附件对象") public DefaultFile getFileInfo(@RequestBody FileReqVo fileReqVo) { DefaultFile file = fileManager.getFileInfo(fileReqVo); return file; } @RequestMapping(value = "fileGet", method = RequestMethod.GET, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "获得附件对象", httpMethod = "GET", notes = "获得附件对象") public DefaultFile edit(@ApiParam(name = "id", value = "主键") @RequestParam String id) { DefaultFile file = null; if (StringUtil.isNotEmpty(id)) { file = fileManager.get(id); } return file; } @RequestMapping(value = "remove", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "批量删除附件", httpMethod = "POST", notes = "批量删除附件") public CommonResult remove(@ApiParam(name = "ids", value = "附件ID!多个ID用,分割") @RequestBody String ids) throws Exception { String[] aryIds = null; if (StringUtil.isNotEmpty(ids)) { aryIds = ids.split(","); } fileManager.delSysFileByIds(aryIds); return new CommonResult(true, "删除附件成功", null); } @RequestMapping(value = "uploadFileForConfig", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "批量附件上传操作", httpMethod = "POST", notes = "批量附件上传操作") public UploadResult uploadForConfig(@ApiParam(name = "bizCode", value = "附件上传编码",required = true) @RequestParam String bizCode, @ApiParam(name = "bizId", value = "业务ID",required = false) @RequestParam String bizId, @ApiParam(name = "bizType", value = "业务分类,业务内部的类别",required = false) @RequestParam String bizType, @ApiParam(name = "files", value = "上传的文件流") @RequestBody List files) throws Exception { DefaultFile file = new DefaultFile(); String account = baseContext.getCurrentUserAccout(); return fileManager.UploadFileForConfig(file, files, bizCode,bizId, bizType,userService.getUserByAccount(account)); } @RequestMapping(value = "fileUpload", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "附件上传操作", httpMethod = "POST", notes = "附件上传操作") public UploadResult fileUpload(@ApiParam(name = "params", value = "格式限定") @RequestParam Map params, @ApiParam(name = "files", value = "上传的文件流") @RequestBody List files, @ApiParam(name = "flowKey", value = "流程key") @RequestParam Optional flowKey) throws Exception { DefaultFile file = new DefaultFile(); if (params.containsKey("file")) { file = JsonUtil.toBean(params.getOrDefault("file", "{}").toString(), DefaultFile.class); } String account = baseContext.getCurrentUserAccout(); return fileManager.uploadFile(file, files, params.getOrDefault("fileFormates", "").toString(), userService.getUserByAccount(account), flowKey.orElse("")); } @RequestMapping(value = "upload", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "附件上传操作", httpMethod = "POST", notes = "附件上传操作") public UploadResult upload(MultipartHttpServletRequest request, @ApiParam(name = "fileFormates", value = "格式要求,多个用逗号隔开") @RequestParam Optional fileFormates, @ApiParam(name = "flowKey", value = "流程key") @RequestParam Optional flowKey, @ApiParam(name = "fileId", value="文件id") @RequestParam(required = false) String fileId) throws Exception { IUser user = null; String account = baseContext.getCurrentUserAccout(); if (StringUtil.isNotEmpty(account)) { user = userService.getUserByAccount(account); } Map fileMaps = request.getFileMap(); Iterator it = fileMaps.values().iterator(); List files = new ArrayList(); while (it.hasNext()) { files.add(it.next()); } DefaultFile file = new DefaultFile(); if (StringUtil.isNotEmpty(fileId)){ file = fileManager.get(fileId); //设文件名称为null,保存时不检查名称 file.setFileName(null); } return fileManager.uploadFile(file, files, fileFormates.orElse(""), user, flowKey.orElse("")); } @RequestMapping(value = "downloadFile", method = RequestMethod.GET, produces = {"application/json; charset=utf-8" }) @ApiOperation(value = "附件下载", httpMethod = "GET", notes = "附件下载") public void downloadFile(HttpServletRequest request, HttpServletResponse response, @ApiParam(name = "fileId", value = "附件ID") @RequestParam String fileId) throws Exception { // response.reset(); response.setContentType("APPLICATION/OCTET-STREAM"); DefaultFile file = null; try (MultiTenantIgnoreResult setThreadLocalIgnore = MultiTenantHandler.setThreadLocalIgnore()) { file = fileManager.get(fileId); } if (BeanUtils.isEmpty(file)) { throw new NotFoundException(String.format("未找到fileId为: %s 的文件", fileId)); } String fileName = file.getFileName() + "." + file.getExtensionName(); String filedisplay = URLEncoder.encode(fileName, "utf-8"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay); response.addHeader("filename", filedisplay); response.setHeader("Access-Control-Allow-Origin", "*"); String type = new MimetypesFileTypeMap().getContentType(new File(file.getFilePath())); response.setContentType(type); fileManager.downloadFile(fileId, response.getOutputStream()); } @RequestMapping(value = "getLogoFile", method = RequestMethod.GET, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "获取租户logo文件", httpMethod = "GET", notes = "根据租户id获取租户logo文件") public void getLogoFile(HttpServletRequest request, HttpServletResponse response, @ApiParam(name = "tenantId", value = "租户id") @RequestParam String tenantId, @ApiParam(name = "logoType", value = "logo类型:manage(管理端)、front(应用端)") @RequestParam String logoType) throws Exception { response.setContentType("APPLICATION/OCTET-STREAM"); DefaultFile file = null; JsonNode tenantNode = ucFeignService.getTenantById(tenantId); String logoTypeField = "manageLogo"; if("front".equals(logoType)){ logoTypeField = "frontLogo"; } ArrayNode logoNode = (ArrayNode) JsonUtil.toJsonNode(tenantNode.get(logoTypeField).asText()); String fileId = logoNode.get(0).get("id").asText(); file = fileManager.get(fileId); if (BeanUtils.isEmpty(file)) { throw new NotFoundException(String.format("未找到fileId为: %s 的文件", fileId)); } String fileName = file.getFileName() + "." + file.getExtensionName(); String filedisplay = URLEncoder.encode(fileName, "utf-8"); response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay); response.addHeader("filename", filedisplay); response.setHeader("Access-Control-Allow-Origin", "*"); String type = new MimetypesFileTypeMap().getContentType(new File(file.getFilePath())); response.setContentType(type); fileManager.downloadFile(fileId, response.getOutputStream()); } @RequestMapping(value = "getFileType", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "根据附件id取得附件类型。", httpMethod = "POST", notes = "根据附件id取得附件类型。") public String getFileType(@ApiParam(name = "fileId", value = "附件id") @RequestBody String fileId) throws IOException { DefaultFile DefaultFile = null; String type = "doc"; if (StringUtil.isNotEmpty(fileId)) { DefaultFile = fileManager.get(fileId); type = DefaultFile.getExtensionName().toLowerCase(); } return type; } @RequestMapping(value = "setXbTypeId", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "修改附件分类。", httpMethod = "POST", notes = "修改附件分类。") public CommonResult setXbTypeId(@ApiParam(name = "fileId", value = "附件id") @RequestBody List fileId, @ApiParam(name = "xbTypeId", value = "分类ID") @RequestParam String xbTypeId, @ApiParam(name = "type", value = "分类名称") @RequestParam String type) throws Exception { fileManager.setXbTypeId(fileId, xbTypeId, type); return new CommonResult(true, "设置附件分类成功", null); } @RequestMapping(value = "updateFileExtraProp", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "更新附件的属性成功", httpMethod = "POST", notes = "更新附件的属性成功(包含扩展属性、流程实例ID、节点名称、流程标题、附件来源、所属分类)") public CommonResult updateFileExtraProp( @ApiParam(name = "files", value = "附件列表") @RequestBody List files) throws Exception { fileManager.updateFileExtraProp(files); return new CommonResult(true, "更新附件的属性成功", null); } @RequestMapping(value = "preview", method = RequestMethod.GET, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "附件预览", httpMethod = "GET", notes = "附件预览") public void preview(HttpServletRequest request, HttpServletResponse response, @ApiParam(name = "fileId", value = "附件ID") @RequestParam String fileId) throws Exception { // response.reset(); try (MultiTenantIgnoreResult setThreadLocalIgnore = MultiTenantHandler.setThreadLocalIgnore()) { response.setContentType("text/html; charset=UTF-8"); response.setContentType("image/jpeg"); DefaultFile file = null; file = fileManager.get(fileId); if (BeanUtils.isEmpty(file)) { return; } String fileName = file.getFileName() + "." + file.getExtensionName(); String filedisplay = fileName; String agent = request.getHeader("USER-AGENT"); if (agent != null && agent.indexOf("MSIE") == -1 && agent.indexOf("Trident") == -1) { filedisplay = "=?UTF-8?B?" + (new String(Base64.getBase64(filedisplay))) + "?="; } else { filedisplay = URLEncoder.encode(filedisplay, "utf-8"); } response.addHeader("filename", filedisplay); response.setHeader("Access-Control-Allow-Origin", "*"); fileManager.downloadFile(fileId, response.getOutputStream()); } catch (Exception e) { logger.error("预览附件失败"); } } @RequestMapping(value = "wordPrint", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "word模板打印", httpMethod = "POST", notes = "word模板打印") public String wordPrint(@ApiParam(name = "objectNode", value = "Json对象") @RequestBody ObjectNode objectNode) throws Exception { String boData = objectNode.get("boData").toString(); String fileId = objectNode.get("fileId").asText(); String subject = objectNode.get("subject").asText(); ArrayNode flowOpinions = (ArrayNode) objectNode.get("flowOpinions"); String scriptStr = objectNode.get("scriptStr").asText(); DefaultFile defaultFile = fileManager.get(fileId); DefaultFile model = new DefaultFile(); model.setId(UniqueIdUtil.getSuid()); String outputFilePath = AppFileUtil .createFilePath("print" + File.separator + baseContext.getCurrentUserAccout(), model.getId() + "." + defaultFile.getExtensionName()); String saveOutputFilePath=this.printFile(boData, defaultFile, outputFilePath, flowOpinions, scriptStr, model.getId()); // 新增打印记录 try { if (flowOpinions.size() > 0) { String defId = objectNode.get("defId").asText(); String nodeId = objectNode.get("nodeId").asText(); ObjectNode opinion = (ObjectNode) flowOpinions.get(0); ObjectNode record = JsonUtil.getMapper().createObjectNode(); record.put("procInstId", opinion.get("procInstId").asText());// procInstId record.put("nodeId", nodeId); record.put("procDefId", defId); record.put("formKey", objectNode.get("formKey").asText()); record.put("templateId", fileId); record.put("templateName", defaultFile.getFileName()); record.put("fileId", model.getId()); workflowFeignService.addPrintLog(record); } } catch (Exception e) { System.out.println("新增打印记录失败:" + e.getMessage()); } model.setFileName(subject); model.setStoreType(AppFileUtil.getSaveType("")); model.setFilePath(outputFilePath.replace(AppFileUtil.getAttachPath() + File.separator, "")); model.setExtensionName(defaultFile.getExtensionName()); model.setIsDel((short) 0); model.setCreateTime(DateUtil.getCurrentDate()); if(!model.getStoreType().equals(DefaultFile.SAVE_TYPE_FOLDER)){ fileManager.uploadFile(model,new FileInputStream(saveOutputFilePath)); }else{ fileManager.create(model); } return model.getId(); } private String printFile(String boData, DefaultFile defaultFile, String outputFilePath, ArrayNode flowOpinions, String scriptStr,String fileId) throws Exception { Map boMap = new HashMap(); Map twiceMap = new HashMap(); AtomicBoolean isSubHtml= new AtomicBoolean(false); // 配置 Configure config = Configure.newBuilder().setElMode(ELMode.SPEL_MODE).setValidErrorHandler(new Configure.ClearHandler()).build(); JsonUtil.toMap(boData).values().forEach(item -> { ((Map) item).forEach((key, val) -> { Object printObj=val;//模板支持Sping表达式之后1对1子表套打有问题 if (key.toString().startsWith("sub_")) { if(HtmlUtil.isHtml(printObj.toString())){ isSubHtml.set(true); } if(val instanceof List && ((List) val).size()==1){ Map subMapKey= (Map) ((List) val).get(0); printObj=subMapKey; } config.customPolicy(key.toString(), new DetailTablePolicy()); } boMap.put(key, printObj); if (HtmlUtil.isHtml(printObj.toString())) {//如果是富文本,则套打子文档 handRichtext(key.toString(), val.toString(), boMap); }else if(BeanUtils.isNotEmpty(val)) {//判断是否签章和图片,如果是则进行特殊套打 HtmlUtil.printPicture(key.toString() , printObj.toString(), boMap, twiceMap); } }); }); config.customPolicy("flowOpinions", new InstanceFlowOpinions()); boMap.put("flowOpinions", flowOpinions); String filePath = defaultFile.getFilePath(); String fullPath = StringUtil.trimSufffix(AppFileUtil.getAttachPath(), File.separator) + File.separator + filePath.replace("/", File.separator); outputFilePath = StringUtil.trimSufffix(AppFileUtil.getAttachPath(), File.separator) + outputFilePath.replace("/", File.separator); String[] paths = outputFilePath.split(fileId); if(paths.length>1){ if(!FileUtil.isExistFile(paths[0])){ FileUtil.createFolder(paths[0], false); } } // 在生成word前先执行脚本,用于替换打印的值(比如实际值为1或者2,想显示的值为男与女,用java 脚本进行判断处理) if (StringUtil.isNotEmpty(scriptStr)) { Map params = new HashMap(); params.put("boMap", boMap); params.putAll(boMap); groovyScriptEngine.executeString(scriptStr, params); } //如果是ftp存储,需要先从ftp下载文件到磁盘目录 if(!new File(fullPath).exists()){ fileManager.downloadFileToPath(defaultFile, fullPath); } XWPFTemplate template = XWPFTemplate.compile(fullPath, config); //处理模板中存在富文本标识,但是富文本值为空的情况 List templates = template.getElementTemplates(); for (MetaTemplate metaTemplate : templates) { String code = metaTemplate.variable(); if(code.startsWith("{{+")) { code = code.replaceAll("\\{", ""); code = code.replaceAll("\\+", ""); code = code.replaceAll("\\}", ""); if(BeanUtils.isEmpty(boMap.get(code))) { handRichtext(code, "", boMap); } } } template.render(boMap); FileOutputStream out = new FileOutputStream(outputFilePath); template.write(out); out.flush(); out.close(); template.close(); if(isSubHtml.get()){//如果子表里面有富文本 再次套打 Configure subConfig = Configure.newBuilder().setElMode(ELMode.SPEL_MODE).build(); XWPFTemplate template2 = XWPFTemplate.compile(outputFilePath, subConfig).render(boMap); FileOutputStream out2 = new FileOutputStream(outputFilePath); template2.write(out2); out2.flush(); out2.close(); template2.close(); } if(!twiceMap.isEmpty()) { //签章图片用#作为标示符(仅在二次套打中使用) Configure twiceConfig = Configure.newBuilder().setElMode(ELMode.SPEL_MODE).addPlugin('#', new SignaturePictureRenderPolicy()).build(); XWPFTemplate template2 = XWPFTemplate.compile(outputFilePath,twiceConfig).render(twiceMap); FileOutputStream out2 = new FileOutputStream(outputFilePath); template2.write(out2); out2.flush(); out2.close(); template2.close(); } return outputFilePath; } /** * 富文本套打处理 * @param key * @param boMap */ private void handRichtext(String key,String text,Map boMap) { if(boMap.get(key) instanceof List){ List subList= (List) boMap.get(key); subList.forEach(subMap->{ subMap.forEach((subKey,subValue)->{ if(HtmlUtil.isHtml(subValue.toString())){ File docxFile = HtmlUtil.getRichtextToDocx(subValue.toString()); subMap.put(subKey,new DocxRenderData(docxFile)); if(docxFile != null && docxFile.exists()) { docxFile.delete(); } } }); }); }else if(boMap.get(key) instanceof Map){ Map subMap= (Map) boMap.get(key); subMap.forEach((subKey,subValue)->{ if(HtmlUtil.isHtml(subValue.toString())){ File docxFile = HtmlUtil.getRichtextToDocx(subValue.toString()); subMap.put(subKey,new DocxRenderData(docxFile)); if(docxFile != null && docxFile.exists()) { docxFile.delete(); } } }); }else{ File docxFile = HtmlUtil.getRichtextToDocx(text); boMap.put(key, new DocxRenderData(docxFile)); //删除临时docx文件 if(docxFile != null && docxFile.exists()) { docxFile.delete(); } } } @RequestMapping(value = "getFileBytesById", method = RequestMethod.GET, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "附件下载", httpMethod = "GET", notes = "附件下载") public byte[] getFileBytesById(@ApiParam(name = "fileId", value = "附件ID") @RequestParam String fileId) throws Exception { return fileManager.getFileBytesById(fileId); } @RequestMapping(value="/importSignature",method=RequestMethod.POST, produces = {"application/json; charset=utf-8" }) @ApiOperation(value = "批量导入签章", httpMethod = "POST", notes = "批量导入签章") public CommonResult importSignature(@ApiParam(name="file",value="导入的压缩文件(.zip或.rar)",required=true) @RequestBody MultipartFile file, @ApiParam(name="repeatConver",value="当用户已存在签章时是否覆盖",required=false) @RequestParam Optional repeatConver) throws Exception{ return fileManager.importSignature(file, repeatConver.orElse(true)); } @RequestMapping(value = "/md5Check", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "校验文件的MD5值", httpMethod = "POST", notes = "校验文件的MD5值") public Map md5Check(@RequestParam("fileSize") Long fileSize, @RequestParam("md5Value") String md5Value) throws Exception { DefaultFile file = this.baseService.queryByMd5AndSize(fileSize, md5Value); String fileID = ""; if(BeanUtils.isNotEmpty(file)){ fileID =file.getId(); } List fileZoneList = new ArrayList(); if (StringUtil.isEmpty(fileID)) { fileZoneList = this.fileZonedManager.queryByMd5Value(md5Value,fileSize); } Map returnMap = new HashMap<>(); returnMap.put("uploaded", fileID); returnMap.put("uploadedChunkList", fileZoneList); return returnMap; } @RequestMapping(value = "/uploadZone", method = RequestMethod.POST, produces = { "application/json; charset=utf-8" }) @ApiOperation(value = "上传切片文件", httpMethod = "POST", notes = "上传切片文件") public Map upload(@RequestParam("zone") MultipartFile chunk, FileZone fileZone, String fileName,String bizCode,String bizId, String folder) throws IOException { String filePath = SysPropertyUtil.getByAlias("file.upload"); String path_date = cn.hutool.core.date.DateUtil.format(new Date(), "yyyy") + File.separator + cn.hutool.core.date.DateUtil.format(new Date(), "MMdd") + File.separator + cn.hutool.core.date.DateUtil.format(new Date(), "HH"); if(StringUtil.isNotEmpty(folder)){ path_date = path_date+ File.separator+folder; } if(fileName.equals("blob")){ fileName=fileZone.getZoneName(); } String fullPath = filePath + File.separator + path_date+File.separator + fileName; String extName = FileUtil.getFileExt(fileName); File file = new File(filePath + File.separator + path_date+File.separator); if(!file.exists()){ file.mkdirs(); } Map returnMap = new HashMap<>(); // 模拟上传出错 // Integer uploadTimes = times.get(fileChunk.getChunkName()); // if (uploadTimes == null) { // times.put(fileChunk.getChunkName(), 1); // // return false; // } // 模块写入对应的位置 try(RandomAccessFile rf = new RandomAccessFile(fullPath,"rw")) { rf.seek(fileZone.getZoneStartSize()); rf.write(chunk.getBytes()); } catch (Exception e) { returnMap.put("flag", false); returnMap.put("id", ""); return returnMap; } // chunk 记录到数据库 String filemd5= ""; if(StringUtil.isEmpty(fileZone.getZoneMd5())){ filemd5= DigestUtils.md5DigestAsHex(chunk.getInputStream()); fileZone.setZoneMd5(filemd5); }else{ filemd5=fileZone.getZoneMd5(); } fileZone.setZoneRecordTime(LocalDateTime.now()); fileZone.setZoneSuffix(extName); fileZone.setZonePath(fullPath); fileZonedManager.create(fileZone); Integer chunkSize = fileZonedManager.countByMd5AndSize(fileZone.getZoneTotalMd5(),fileZone.getZoneTotalSize()); String fileId = ""; if (chunkSize.equals(fileZone.getZoneTotalCount())) { // 删除 chunk 记录 fileZonedManager.removeZoneByMd5AndSize(fileZone.getZoneTotalMd5(),fileZone.getZoneTotalSize()); // 增加 file 记录 DefaultFile fileRecord = new DefaultFile(); fileRecord.setBizCode(bizCode); fileRecord.setBizId(bizId); fileRecord.setByteCount(fileZone.getZoneTotalSize()); fileRecord.setMd5Value(fileZone.getZoneTotalMd5()); fileRecord.setFileName(fileName); fileRecord.setServerLocalName(fileName); fileRecord.setServerLocalPath(fullPath); fileRecord.setFilePath(fullPath.replace(filePath, "")); fileRecord.setIsZone(1); fileRecord.setStoreType("folder"); fileRecord.setExtensionName(extName); fileRecord.setZoneTotal(fileZone.getZoneTotalCount()); fileId = this.baseService.insertFile(fileRecord); } returnMap.put("flag", true); returnMap.put("id", fileId); return returnMap; } }