diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/controller/EdFileInfoController.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/controller/EdFileInfoController.java index 3c6af82..b514500 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/controller/EdFileInfoController.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/controller/EdFileInfoController.java @@ -1,14 +1,15 @@ package com.electromagnetic.industry.software.manage.controller; import com.electromagnetic.industry.software.common.resp.ElectromagneticResult; +import com.electromagnetic.industry.software.manage.pojo.req.FileChunkDTO; import com.electromagnetic.industry.software.manage.pojo.req.FileInfoQueryDTO; +import com.electromagnetic.industry.software.manage.pojo.req.UpdateFileInfoDTO; import com.electromagnetic.industry.software.manage.service.EdFileInfoService; +import io.swagger.annotations.ApiOperation; import org.springframework.core.io.InputStreamResource; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; @@ -42,8 +43,10 @@ public class EdFileInfoController { } @RequestMapping("upload") - public ElectromagneticResult upload() { - return null; + public ElectromagneticResult upload(@RequestParam("parentId") String parentId, + @RequestParam("file") MultipartFile file, + @RequestParam("strategy") Integer strategy) { + return edFileInfoService.upload(parentId, file, strategy); } @RequestMapping("download") @@ -52,37 +55,53 @@ public class EdFileInfoController { } @RequestMapping("updateFileInfo") - public ElectromagneticResult updateFileInfo() { - return null; - } - - @RequestMapping("deleteFile") - public ElectromagneticResult deleteFile() { - return null; + public ElectromagneticResult updateFileInfo(@RequestBody UpdateFileInfoDTO updateFileInfoDTO) { + return edFileInfoService.updateFileInfo(updateFileInfoDTO); } @RequestMapping("moveFile") - public ElectromagneticResult moveFile() { - return null; + public ElectromagneticResult moveFile(@RequestParam("id") String id, + @RequestParam("targetFolderId") String targetFolderId, + @RequestParam("strategy") Integer strategy) { + return edFileInfoService.moveFile(id, targetFolderId, strategy); } @RequestMapping("copyFile") - public ElectromagneticResult copyFile() { - return null; + public ElectromagneticResult copyFile(@RequestParam("id") String id, + @RequestParam("targetFolderId") String targetFolderId, + @RequestParam("strategy") Integer strategy) { + return edFileInfoService.copyFile(id, targetFolderId, strategy); } @RequestMapping("versionView") - public ElectromagneticResult versionView() { - return null; - } + public ElectromagneticResult versionView(@RequestParam String fileId) { + return edFileInfoService.versionView(fileId); + } @RequestMapping("versionBack") - public ElectromagneticResult versionBack() { - return null; + public ElectromagneticResult versionBack(@RequestParam String fileId, @RequestParam int targetVersion) { + return edFileInfoService.versionBack(fileId, targetVersion); } @RequestMapping("batchExport") - public ElectromagneticResult batchExport() { - return null; + public ResponseEntity batchExport(@RequestParam String dataIdArr, HttpServletResponse response) throws IOException { + return edFileInfoService.batchExport(dataIdArr, response); + } + + @RequestMapping(value = "/mergeChunks",method = RequestMethod.GET) + public ElectromagneticResult mergeChunks(@RequestParam String identifier, + @RequestParam String fileName, + @RequestParam Integer totalChunks) { + return edFileInfoService.mergeChunks(identifier, fileName, totalChunks); + } + + @RequestMapping(value = "/batchImport",method = RequestMethod.POST) + public ElectromagneticResult batchImport(FileChunkDTO fileChunkDTO) { + return edFileInfoService.batchImport(fileChunkDTO); + } + + @RequestMapping(value = "/batchImport",method = RequestMethod.GET) + public ElectromagneticResult checkChunkExist(FileChunkDTO fileChunkDTO) { + return edFileInfoService.checkChunkExist(fileChunkDTO); } } diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/models/EdFileInfo.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/models/EdFileInfo.java index 2c6a826..561bdd6 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/models/EdFileInfo.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/models/EdFileInfo.java @@ -2,17 +2,39 @@ package com.electromagnetic.industry.software.manage.pojo.models; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.electromagnetic.industry.software.common.enums.EffectFlagEnum; +import com.electromagnetic.industry.software.common.util.EleCommonUtil; +import com.electromagnetic.industry.software.common.util.IdWorker; +import com.electromagnetic.industry.software.common.util.UserThreadLocal; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import lombok.experimental.FieldNameConstants; +import java.util.Date; + @EqualsAndHashCode(callSuper = true) @TableName("ed_file_info") @Accessors(chain = true) @Data @FieldNameConstants public class EdFileInfo extends BaseModel { + + public void newInit() { + String userId = UserThreadLocal.getUserId(); + String newFileDbId = IdWorker.getSnowFlakeIdString(); + String fileTime = EleCommonUtil.getNowTimeStr(); + Date now = new Date(); + this.setUpdatedBy(userId); + this.setId(newFileDbId); + this.setUpdateTime(now); + this.setCreatedTime(now); + this.setFileTime(fileTime); + this.setCreatedBy(userId); + this.setFileId(newFileDbId); + this.setEffectFlag(EffectFlagEnum.EFFECT.code); + } + /** * 主键ID */ diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/req/UpdateFileInfoDTO.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/req/UpdateFileInfoDTO.java new file mode 100644 index 0000000..68d493b --- /dev/null +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/req/UpdateFileInfoDTO.java @@ -0,0 +1,12 @@ +package com.electromagnetic.industry.software.manage.pojo.req; + +import lombok.Data; + +@Data +public class UpdateFileInfoDTO { + + private String id; + private String fileName; + private String fileNote; + +} diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/resp/FileVersionViewVO.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/resp/FileVersionViewVO.java new file mode 100644 index 0000000..dd48a27 --- /dev/null +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/pojo/resp/FileVersionViewVO.java @@ -0,0 +1,13 @@ +package com.electromagnetic.industry.software.manage.pojo.resp; + +import lombok.Data; + +@Data +public class FileVersionViewVO { + private String id; + private String fileName; + private Integer fileVersion; + private Integer preVersion; + private String fileCode; + private Integer effectFlag; +} diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/EdFileInfoService.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/EdFileInfoService.java index ac7e497..52ad34c 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/EdFileInfoService.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/EdFileInfoService.java @@ -1,9 +1,12 @@ package com.electromagnetic.industry.software.manage.service; import com.electromagnetic.industry.software.common.resp.ElectromagneticResult; +import com.electromagnetic.industry.software.manage.pojo.req.FileChunkDTO; import com.electromagnetic.industry.software.manage.pojo.req.FileInfoQueryDTO; +import com.electromagnetic.industry.software.manage.pojo.req.UpdateFileInfoDTO; import org.springframework.core.io.InputStreamResource; import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -46,4 +49,80 @@ public interface EdFileInfoService { * @return */ ResponseEntity download(String id, HttpServletResponse response); + + /** + * 更新文件信息 + * @param updateFileInfoDTO + */ + ElectromagneticResult updateFileInfo(UpdateFileInfoDTO updateFileInfoDTO); + + /** + * 版本回退 + * @param fileId + * @param targetVersion + * @return + */ + ElectromagneticResult versionBack(String fileId, int targetVersion); + + /** + * 查看分片是否存在 + * @param fileChunkDTO + * @return + */ + ElectromagneticResult checkChunkExist(FileChunkDTO fileChunkDTO); + + /** + * 批量导入 + * @param fileChunkDTO + * @return + */ + ElectromagneticResult batchImport(FileChunkDTO fileChunkDTO); + + /** + * 合并分片 + * @param identifier + * @param fileName + * @param totalChunks + * @return + */ + ElectromagneticResult mergeChunks(String identifier, String fileName, Integer totalChunks); + + /** + * 导出 + * @param dataIdArr + * @return + */ + ResponseEntity batchExport(String dataIdArr, HttpServletResponse response) throws IOException; + + /** + * 文件上传 + * @param parentId + * @param file + * @param strategy + * @return + */ + ElectromagneticResult upload(String parentId, MultipartFile file, Integer strategy); + + /** + * 版本查看 + * @param fileId + * @return + */ + ElectromagneticResult versionView(String fileId); + + /** + * 移动文件 + * @param id + * @param targetFolderId + * @return + */ + ElectromagneticResult moveFile(String id, String targetFolderId, Integer strategy); + + /** + * 复制文件 + * @param id + * @param targetFolderId + * @return + */ + ElectromagneticResult copyFile(String id, String targetFolderId, Integer strategy); } diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/CommonService.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/CommonService.java index ebd6ad5..2d6fbd5 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/CommonService.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/CommonService.java @@ -6,7 +6,9 @@ import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.TreeNodeConfig; import cn.hutool.core.lang.tree.TreeUtil; import cn.hutool.core.text.StrFormatter; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -33,6 +35,7 @@ import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.File; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import static com.electromagnetic.industry.software.common.cons.ElectromagneticConstants.*; @@ -42,6 +45,9 @@ public class CommonService { private final EleLog log = new EleLog(CommonService.class); private static final Map FILE_TYPE_ENUM = new HashMap<>(); + + private static final Map ID_NAME = new ConcurrentHashMap<>(); + @Value("${prj.folder.max.length}") private int prjFolderMaxLength; @@ -98,11 +104,19 @@ public class CommonService { public String getFileSysPath(String dbPath) { ArrayList paths = CollUtil.newArrayList(dbPath.split(MYSQL_FILE_PATH_SPLIT)); - String path = getPath(paths); + String path = getDbPath(paths); return eleDataPath + File.separator + path; } - public String getPath(List ids) { + public String getDbPath(String dbPath) { + List paths = CollUtil.newArrayList(dbPath.split(MYSQL_FILE_PATH_SPLIT)); + return getDbPath(paths); + } + + public String getDbPath(List ids) { + + // TODO cache + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(EdFileInfo.class) .select(EdFileInfo::getId, EdFileInfo::getFileName) .in(EdFileInfo::getId, ids); @@ -128,7 +142,7 @@ public class CommonService { .likeRight(EdFileInfo::getFilePath, id)); } - public ElectromagneticResult addFolder(String parentId, String folderName, boolean maxLengthCheck, boolean isPrjDir) { + public ElectromagneticResult addFolder(String parentId, String folderName, boolean maxLengthCheck, boolean isPrjDir, String folderId) { // 验证名称是否合法 Assert.isTrue(EleCommonUtil.isFileNameValid(folderName), "文件名不符合规范,只能包含中文字符、下划线、连字符、加号、数字和英文字符且长度小于32。"); @@ -165,15 +179,13 @@ public class CommonService { } try { - int id = Integer.parseInt(edFileInfoMapper.maxPrjId()); Date now = new Date(); String currentUserId = UserThreadLocal.getUserId(); - String newFolderId = String.valueOf(id + 1); - String path = currentPath + MYSQL_FILE_PATH_SPLIT + newFolderId; + String path = currentPath + MYSQL_FILE_PATH_SPLIT + folderId; EdFileInfo fileInfo = new EdFileInfo(); String nowTimeStr = EleCommonUtil.getNowTimeStr(); - fileInfo.setId(newFolderId) - .setFileId(newFolderId) + fileInfo.setId(folderId) + .setFileId(folderId) .setFileName(folderName) .setFileVersion(FILE_START_VERSION) .setParentId(parentId) @@ -192,7 +204,7 @@ public class CommonService { .setUpdatedBy(currentUserId); edFileInfoMapper.insert(fileInfo); // 保存到文件系统 - String targetFilePath = getEleDataPath() + File.separator + getPath(paths) + File.separator + folderName; + String targetFilePath = getEleDataPath() + File.separator + getDbPath(paths) + File.separator + folderName; fileSystemService.createDirectory(targetFilePath); return ElectromagneticResultUtil.success(true); } catch (Exception e) { @@ -294,4 +306,15 @@ public class CommonService { throw new BizException(-1, info); } } + + public String getCodePathByDbPath(String dbPath) { + List paths = StrUtil.split(dbPath, MYSQL_FILE_PATH_SPLIT); + List reversePaths = CollUtil.reverse(paths); + for (String path : reversePaths) { + if (path.length() == 6) { + return path; + } + } + return null; + } } diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdFileInfoServiceImpl.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdFileInfoServiceImpl.java index 7316021..95927a4 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdFileInfoServiceImpl.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdFileInfoServiceImpl.java @@ -2,44 +2,86 @@ package com.electromagnetic.industry.software.manage.service.serviceimpl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.codec.Base64; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ZipUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.symmetric.AES; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.electromagnetic.industry.software.common.enums.EffectFlagEnum; +import com.electromagnetic.industry.software.common.enums.EleDataTypeEnum; +import com.electromagnetic.industry.software.common.enums.PublishEnum; import com.electromagnetic.industry.software.common.exception.BizException; import com.electromagnetic.industry.software.common.resp.ElectromagneticResult; -import com.electromagnetic.industry.software.common.util.EleLog; -import com.electromagnetic.industry.software.common.util.ElectromagneticResultUtil; +import com.electromagnetic.industry.software.common.util.*; import com.electromagnetic.industry.software.manage.mapper.EdFileInfoMapper; import com.electromagnetic.industry.software.manage.pojo.models.EdFileInfo; import com.electromagnetic.industry.software.manage.pojo.other.FileInfoDTO; +import com.electromagnetic.industry.software.manage.pojo.req.FileChunkDTO; +import com.electromagnetic.industry.software.manage.pojo.req.FileChunkResultDTO; import com.electromagnetic.industry.software.manage.pojo.req.FileInfoQueryDTO; +import com.electromagnetic.industry.software.manage.pojo.req.UpdateFileInfoDTO; import com.electromagnetic.industry.software.manage.pojo.resp.FileInfoQueryPageVO; +import com.electromagnetic.industry.software.manage.pojo.resp.FileVersionViewVO; import com.electromagnetic.industry.software.manage.service.EdFileInfoService; +import com.electromagnetic.industry.software.manage.service.FileSystemService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.BindException; -import java.util.List; -import java.util.Objects; +import java.io.*; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; + +import static com.electromagnetic.industry.software.common.cons.ElectromagneticConstants.*; @Service public class EdFileInfoServiceImpl extends ServiceImpl implements EdFileInfoService { @Resource private CommonService commonService; - private EleLog log = new EleLog(EdFileInfoServiceImpl.class); + @Autowired + private FileSystemService fileSystemService; + @Resource + private Environment environment; + + private String downloadDataDir = ""; + private String uploadDataDir = ""; + + + @Value("${file.security.passwd}") + private String password; + + + @PostConstruct + public void init() { + String osName = System.getProperty("os.name").toLowerCase(); + uploadDataDir = osName.startsWith("win") ? environment.getProperty("data.upload.windows.tmp.path") : environment.getProperty("data.upload.linux.tmp.path"); + downloadDataDir = osName.startsWith("win") ? environment.getProperty("data.download.windows.tmp.path") : environment.getProperty("data.download.linux.tmp.path"); + } /** * 查询文件列表 @@ -86,12 +128,12 @@ public class EdFileInfoServiceImpl extends ServiceImpl createFolder(String parentId, String newFolderName) { - return commonService.addFolder(parentId, newFolderName, false, false); + String folderId = IdWorker.getSnowFlakeIdString(); + return commonService.addFolder(parentId, newFolderName, false, false, folderId); } /** * 项目层级结构查询 - * * @return */ @Override @@ -121,7 +163,6 @@ public class EdFileInfoServiceImpl extends ServiceImpllambdaQuery().eq(EdFileInfo::getId, id)); - String fileSysPath = commonService.getFileSysPath(fileInfo.getFilePath()); + String fileSysPath = commonService.getFileSysPath(fileInfo.getFilePath()) + "." + fileInfo.getFileCode(); Assert.isTrue(FileUtil.exist(fileSysPath), "下载文件不存在。"); FileSystemResource fileSystemResource = new FileSystemResource(fileSysPath); HttpHeaders headers = new HttpHeaders(); @@ -152,4 +193,502 @@ public class EdFileInfoServiceImpl extends ServiceImpl updateFileInfo(UpdateFileInfoDTO updateFileInfoDTO) { + try { + EdFileInfo fileInfo = this.baseMapper.selectById(updateFileInfoDTO.getId()); + this.baseMapper.update(null, Wrappers.lambdaUpdate(EdFileInfo.class) + .eq(EdFileInfo::getId, updateFileInfoDTO.getId()) + .set(EdFileInfo::getFileName, updateFileInfoDTO.getFileName()) + .set(EdFileInfo::getFileNote, updateFileInfoDTO.getFileNote())); + String sysFilePath = commonService.getFileSysPath(fileInfo.getFilePath()); + fileSystemService.renameFile(sysFilePath, updateFileInfoDTO.getFileName()); + return ElectromagneticResultUtil.success(true); + } catch (Exception e) { + String info = "更新文件信息失败。"; + log.error(info, e); + throw new BizException(-1, e.getMessage()); + } + } + + /** + * 版本回退 + * + * @param fileId + * @param targetVersion + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public ElectromagneticResult versionBack(String fileId, int targetVersion) { + + try { + this.baseMapper.update(null, Wrappers.lambdaUpdate(EdFileInfo.class) + .set(EdFileInfo::getFileId, fileId) + .set(EdFileInfo::getEffectFlag, false)); + this.baseMapper.update(null, Wrappers.lambdaUpdate(EdFileInfo.class) + .set(EdFileInfo::getEffectFlag, true) + .eq(EdFileInfo::getFileId, fileId) + .eq(EdFileInfo::getFileVersion, targetVersion)); + } catch (Exception e) { + String info = "版本回退失败。"; + log.error(info, e); + throw new BizException(-1, info); + } + return ElectromagneticResultUtil.success(true); + } + + /** + * 查看分片是否存在 + * @param fileChunkDTO + * @return + */ + @Override + public ElectromagneticResult checkChunkExist(FileChunkDTO fileChunkDTO) { + String currentUserId = UserThreadLocal.getUserId(); + String userUploadFolder = uploadDataDir + File.separator + currentUserId; + String identifier = fileChunkDTO.getIdentifier(); + List uploadedChunks = getUploadedChunks(identifier, userUploadFolder); + return ElectromagneticResultUtil.success(new FileChunkResultDTO(false, new HashSet<>(uploadedChunks))); + } + + private List getUploadedChunks(String identifier, String destPath) { + String filePath = destPath + File.separator + identifier; + if (!FileUtil.exist(new File(filePath))) { + return new ArrayList<>(); + } + + return FileUtil.listFileNames(destPath) + .stream() + .map(e -> e.replace(UPLOAD_FILE_CHUNK_SUFFIX, "")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } + + /** + * 批量导入 + * @param fileChunkDTO + * @return + */ + @Override + public ElectromagneticResult batchImport(FileChunkDTO fileChunkDTO) { + String currentUserId = UserThreadLocal.getUserId(); + String identifier = fileChunkDTO.getIdentifier(); + // 首先检查该分片有没被上传,如果有则禁止上传 + String destPath = uploadDataDir + File.separator + currentUserId + File.separator + identifier + fileChunkDTO.getChunkNumber() + UPLOAD_FILE_CHUNK_SUFFIX; + boolean exist = FileUtil.exist(destPath); + if (exist) { + return ElectromagneticResultUtil.fail("-1", "文件已经存在,请勿重复上传"); + } + try ( + InputStream inputStream = fileChunkDTO.getFile().getInputStream(); + FileOutputStream fileOutputStream = new FileOutputStream(destPath); + ) { + IoUtil.copy(inputStream, fileOutputStream); + } catch (IOException ioException) { + log.error("上传文件失败...", ioException); + throw new BizException(-1, "上传文件失败"); + } + return ElectromagneticResultUtil.success(fileChunkDTO.getIdentifier()); + } + + /** + * 合并分片 + * @param identifier + * @param fileName + * @param totalChunks + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public ElectromagneticResult mergeChunks(String identifier, String fileName, Integer totalChunks) { + String destZipPath = doSysFileMerge(identifier, fileName, totalChunks); + int index = destZipPath.lastIndexOf(".zip"); + String zipDirPath = destZipPath.substring(0, index); + AES aes = SecureUtil.aes(password.getBytes()); + try( + InputStream inputStream = Files.newInputStream(Paths.get(destZipPath)); + OutputStream outputStream = Files.newOutputStream(Paths.get(zipDirPath)); + ) { + aes.decrypt(inputStream, outputStream, true); + } catch (Exception e) { + String info = "文件上传错误"; + log.error(info, e); + throw new BizException(-1, e.getMessage()); + } + update2Database(zipDirPath); + update2FileSystem(zipDirPath); + return null; + } + + private void update2Database(String colibDirPath) { + + // 首先解密该文件 + AES aes = SecureUtil.aes(password.getBytes()); + String zipFilePath = ""; + try( + InputStream inputStream = Files.newInputStream(Paths.get(colibDirPath)); + OutputStream outputStream = Files.newOutputStream(Paths.get(zipFilePath)); + ) { + aes.decrypt(inputStream, outputStream, true); + } catch (Exception e) { + String info = "文件上传失败"; + log.error(info, e); + throw new BizException(-1, info); + } + String tmpDir = ""; + +// ZipUtil.unzipq + + // TODO 注意 需要reversion + } + + private void update2FileSystem(String zipDirPath) { + } + + /** + * 导出 + * + * @param dataIdArr + * @return + */ + @Override + public ResponseEntity batchExport(String dataIdArr, HttpServletResponse response) throws IOException { + String[] ids = dataIdArr.split(","); + List resFiles = new ArrayList<>(); + for (String id : ids) { + List edFileInfos = this.baseMapper.selectList(Wrappers.lambdaQuery(EdFileInfo.class) + .like(EdFileInfo::getFilePath, MYSQL_FILE_PATH_SPLIT + id + MYSQL_FILE_PATH_SPLIT) + .eq(EdFileInfo::getEffectFlag, true)); + resFiles.addAll(edFileInfos); + } + String prjName = resFiles.stream().filter(e -> e.getParentId().equals(PRJ_PARENT_ID)).findFirst().get().getFileName(); + List folders = resFiles.stream().filter(e -> e.getDataType().equals(EleDataTypeEnum.FOLDER.code)).collect(Collectors.toList()); + List files = resFiles.stream().filter(e -> e.getDataType().equals(EleDataTypeEnum.FILE.code)).collect(Collectors.toList()); + for (EdFileInfo edFileInfo : folders) { + String destFolderPath = downloadDataDir + File.separator + commonService.getFileSysPath(edFileInfo.getFileId()); + FileUtil.mkdir(destFolderPath); + } + for (EdFileInfo edFileInfo : files) { + String filePath = commonService.getFileSysPath(edFileInfo.getFileId()) + edFileInfo.getFileCode() + "." + edFileInfo.getFileCode(); + String destPath = downloadDataDir + File.separator + commonService.getDbPath(edFileInfo.getFileId()); + FileUtil.copy(filePath, destPath, false); + } + String mysqlInfo = JSONUtil.toJsonStr(resFiles); + FileUtil.writeString(mysqlInfo, downloadDataDir + File.separator + "mysql.info", Charset.defaultCharset()); + String exportZipFile = downloadDataDir + File.separator + prjName + ".zip"; + String exportColibFile = downloadDataDir + File.separator + prjName + EXPORT_FILE_SUFFIX; + ZipUtil.zip(downloadDataDir + File.separator + prjName, exportZipFile); + AES aes = SecureUtil.aes(password.getBytes()); + try( + InputStream inputStream = Files.newInputStream(Paths.get(exportZipFile)); + OutputStream outputStream = Files.newOutputStream(Paths.get(exportColibFile)); + ) { + aes.encrypt(inputStream, outputStream, true); + } catch (Exception e) { + String info = "导出失败。"; + log.error(info, e); + throw new BizException(-1, info); + } finally { + FileUtil.del(exportZipFile); + } + File file = new File(exportColibFile); + FileSystemResource fileSystemResource = new FileSystemResource(file); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Cache-Control", "no-cache, no-store, must-revalidate"); + String fileName = Base64.encode(fileSystemResource.getFilename()); + headers.add("Pragma", "no-cache"); + headers.add("Expires", "0"); + response.setHeader("content-disposition","attachment;filename=" + fileName); + + // 构建响应实体(可以返回 upload(String parentId, MultipartFile file, Integer strategy) { + // 首先检查是否是同名文件 + try { + String fileName = file.getOriginalFilename(); + String mainName = FileUtil.mainName(fileName); + String suffix = FileUtil.getSuffix(fileName); + Assert.isTrue(EleCommonUtil.isFileNameValid(fileName), "文件名不符合规范,只能包含中文字符、下划线、连字符、加号、数字和英文字符且长度小于32。"); + Long count = this.baseMapper.selectCount(Wrappers.lambdaQuery(EdFileInfo.class) + .eq(EdFileInfo::getParentId, parentId) + .eq(EdFileInfo::getFileName, mainName) + .eq(EdFileInfo::getEffectFlag, EffectFlagEnum.EFFECT.code) + .eq(EdFileInfo::getFileType, suffix)); + if (count > 0) { + handUploadRepeatFile(parentId, file, strategy); + } else { + EdFileInfo parentFolderInfo = this.baseMapper.selectOne(Wrappers.lambdaQuery(EdFileInfo.class) + .eq(EdFileInfo::getId, parentId) + .eq(EdFileInfo::getEffectFlag, EffectFlagEnum.EFFECT.code)); + EdFileInfo newEdFileInfo = new EdFileInfo(); + newEdFileInfo.newInit(); + String codePathByDbPath = commonService.getCodePathByDbPath(parentFolderInfo.getFilePath()); + String fileCode = commonService.createFileCode(codePathByDbPath, suffix, FILE_START_VERSION, newEdFileInfo.getFileTime()); + newEdFileInfo.setParentId(parentId) + .setFileCode(fileCode) + .setFileName(mainName) + .setFileType(suffix) + .setFileVersion(FILE_START_VERSION) + .setFileSize(file.getSize()) + .setFilePath(parentFolderInfo.getFilePath() + MYSQL_FILE_PATH_SPLIT + newEdFileInfo.getId()) + .setDataType(EleDataTypeEnum.FILE.code) + .setDataStatus(PublishEnum.PUBLISHED.getCode()) + .setEffectFlag(EffectFlagEnum.EFFECT.code) + .setFileCode(fileCode) + .setPrjDir(false); + this.baseMapper.insert(newEdFileInfo); + String fileDestPath = commonService.getFileSysPath(parentFolderInfo.getFileId()) + File.separator + mainName + suffix + "." + fileCode; + fileSystemService.save(file.getInputStream(), fileDestPath); + } + } catch (Exception e) { + String info = "上传文件失败"; + log.error(info, e); + throw new BizException(-1, info); + } + return ElectromagneticResultUtil.success(true); + } + + /** + * 版本查看 + * + * @param fileId + * @return + */ + @Override + public ElectromagneticResult versionView(String fileId) { + List edFileInfos = this.baseMapper.selectList(Wrappers.lambdaQuery(EdFileInfo.class) + .select(EdFileInfo::getId, EdFileInfo::getFileId, EdFileInfo::getFileVersion, EdFileInfo::getPreVersion, EdFileInfo::getFileCode, EdFileInfo::getEffectFlag) + .eq(EdFileInfo::getFileId, fileId)); + List fileVersionViewVOS = BeanUtil.copyToList(edFileInfos, FileVersionViewVO.class); + return ElectromagneticResultUtil.success(fileVersionViewVOS); + } + + /** + * 移动文件 + * + * @param id + * @param targetFolderId + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public ElectromagneticResult moveFile(String id, String targetFolderId, Integer strategy) { + return moveFile(id, targetFolderId, strategy, true); + } + + private void handMoveConflict(String targetFolderId, Integer strategy, EdFileInfo srcFileInfo, EdFileInfo destFolderInfo, boolean deleteSrc) { + if (strategy == 2) { + // 做版本更新 + List sameFileInfos = this.baseMapper.selectList(Wrappers.lambdaQuery(EdFileInfo.class) + .eq(EdFileInfo::getParentId, targetFolderId) + .eq(EdFileInfo::getFileName, srcFileInfo.getFileName()) + .eq(EdFileInfo::getFileType, srcFileInfo.getFileType())); + Integer maxFileVersion = Collections.max(sameFileInfos, Comparator.comparing(EdFileInfo::getFileVersion)).getFileVersion(); + String newFileDbId = IdWorker.getSnowFlakeIdString(); + String fileTime = EleCommonUtil.getNowTimeStr(); + String fileCode = commonService.createFileCode(targetFolderId, srcFileInfo.getFileType(), maxFileVersion + 1, fileTime); + EdFileInfo destSaveFileInfo = BeanUtil.copyProperties(sameFileInfos.get(0), EdFileInfo.class); + destSaveFileInfo.newInit(); + destSaveFileInfo.setFileVersion(maxFileVersion + 1) + .setFilePath(destSaveFileInfo + MYSQL_FILE_PATH_SPLIT + newFileDbId) + .setPreVersion(maxFileVersion) + .setEffectFlag(EffectFlagEnum.EFFECT.code) + .setFileCode(fileCode); + this.baseMapper.insert(destSaveFileInfo); + } else if (strategy == 3) { + // 文件名加“_1”,版本号从100开始 + // 处理MySQL相关逻辑 + EdFileInfo newEdFileInfo = BeanUtil.copyProperties(srcFileInfo, EdFileInfo.class); + newEdFileInfo.newInit(); + newEdFileInfo.setParentId(targetFolderId) + .setFileVersion(FILE_START_VERSION) + .setFileName(srcFileInfo.getFileName() + "_1") + .setFileCode(commonService.createFileCode(targetFolderId, srcFileInfo.getFileType(), FILE_START_VERSION, newEdFileInfo.getFileTime())) + .setFilePath(destFolderInfo.getFilePath() + MYSQL_FILE_PATH_SPLIT + newEdFileInfo.getId()); + this.baseMapper.insert(newEdFileInfo); + // 移动文件 + String srcFileSysPath = commonService.getFileSysPath(srcFileInfo.getFilePath()); + String destFileSysPath = commonService.getFileSysPath(destFolderInfo.getFilePath()); + fileSystemService.moveFile(srcFileSysPath, destFileSysPath); + } + } + + private ElectromagneticResult moveFile(String id, String targetFolderId, Integer strategy, boolean deleteSrc) { + // 获取原文件mysql模型 + EdFileInfo srcFileInfo = this.baseMapper.selectById(id); + // 判断目标路径下是否有同名文件,如果所有的同名文件:1)如果所有文件都已经被作废,则该文件为新文件,版本号从100开始。2)如果有没有被作废的文件,则冲突处理方式按---1-跳过冲突文件 2-做版本更新 3-重命名,文件名加"_1" + List destFolderFiles = this.baseMapper.selectList(Wrappers.lambdaQuery(EdFileInfo.class).eq(EdFileInfo::getParentId, targetFolderId)); + EdFileInfo destFolderInfo = this.baseMapper.selectOne(Wrappers.lambdaQuery(EdFileInfo.class).eq(EdFileInfo::getId, targetFolderId)); + List effectFileInfos = destFolderFiles.stream().filter(e -> Objects.equals(e.getEffectFlag(), EffectFlagEnum.EFFECT.code)).collect(Collectors.toList()); + if (CollUtil.isEmpty(effectFileInfos) || CollUtil.isEmpty(destFolderFiles)) { + // 没有同名文件 + // 首先将信息保存到MySQL + EdFileInfo destSaveFileInfo = BeanUtil.copyProperties(srcFileInfo, EdFileInfo.class); + destSaveFileInfo.newInit(); + String fileTime = EleCommonUtil.getNowTimeStr(); + String newFileCode = commonService.createFileCode(targetFolderId, srcFileInfo.getFileType(), FILE_START_VERSION, fileTime); + destSaveFileInfo.setParentId(targetFolderId) + .setFileVersion(FILE_START_VERSION) + .setFileTime(fileTime) + .setFilePath(destFolderInfo.getFilePath() + MYSQL_FILE_PATH_SPLIT + destSaveFileInfo.getId()) + .setFileCode(newFileCode); + this.baseMapper.insert(destSaveFileInfo); + // 文件系统移动文件 + String srcFilePath = commonService.getFileSysPath(srcFileInfo.getFileId()) + File.separator + srcFileInfo.getFileCode(); + String destFilePath = commonService.getFileSysPath(destFolderInfo.getFileId()) + File.separator + destFolderInfo.getFileCode(); + fileSystemService.moveFile(srcFilePath, destFilePath); + } else { + handMoveConflict(targetFolderId, strategy, srcFileInfo, destFolderInfo, deleteSrc); + } + // 将以前的版本effect全部置为false,删除原目录下的同名文件 + if (deleteSrc) { + this.baseMapper.update(null, Wrappers.lambdaUpdate(EdFileInfo.class) + .set(EdFileInfo::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code) + .eq(EdFileInfo::getParentId, srcFileInfo.getParentId()) + .eq(EdFileInfo::getFileName, srcFileInfo.getFileName()) + .eq(EdFileInfo::getFileType, srcFileInfo.getFileType())); + } + return null; + } + + /** + * 复制文件 + * @param id + * @param targetFolderId + * @return + */ + @Override + public ElectromagneticResult copyFile(String id, String targetFolderId, Integer strategy) { + return moveFile(id, targetFolderId, strategy, false); + } + + private void handUploadRepeatFile(String parentId, MultipartFile file, Integer strategy) throws IOException { + Assert.isTrue(Arrays.asList(1, 2, 3).contains(strategy), "解决同名文件参数错误"); + String fileName = file.getOriginalFilename(); + String mainName = FileUtil.mainName(fileName); + String suffix = FileUtil.getSuffix(fileName); + if (strategy == 2) { + // 版本更新 + // step1:找到同名文件的MySQL对象 + List parentFileInfos = this.baseMapper.selectList(Wrappers.lambdaQuery(EdFileInfo.class) + .eq(EdFileInfo::getParentId, parentId) + .eq(EdFileInfo::getFileName, mainName) + .eq(EdFileInfo::getFileType, suffix)); + EdFileInfo parentFileInfo = this.baseMapper.selectOne(Wrappers.lambdaQuery(EdFileInfo.class) + .eq(EdFileInfo::getId, parentId) + .eq(EdFileInfo::getEffectFlag, EffectFlagEnum.EFFECT.code)); + Integer maxFileVersion = Collections.max(parentFileInfos, Comparator.comparing(EdFileInfo::getFileVersion)).getFileVersion(); + // 找到当前展示的版本 + EdFileInfo effectFileInfo = parentFileInfos.stream().filter(e -> e.getEffectFlag().equals(true)).collect(Collectors.toList()).get(0); + String codePathByDbPath = commonService.getCodePathByDbPath(effectFileInfo.getFilePath()); + String timeStr = EleCommonUtil.getNowTimeStr(); + String fileCode = commonService.createFileCode(codePathByDbPath, suffix, FILE_START_VERSION, timeStr); + // 将原有效的版本置为false + this.baseMapper.update(null, Wrappers.lambdaUpdate(EdFileInfo.class) + .set(EdFileInfo::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code) + .eq(EdFileInfo::getId, effectFileInfo.getId())); + // 新增文件 + EdFileInfo newEdFileInfo = new EdFileInfo(); + newEdFileInfo.newInit(); + newEdFileInfo.setFileId(effectFileInfo.getFileId()) + .setParentId(parentId) + .setFileCode(fileCode) + .setFileName(mainName) + .setFileType(suffix) + .setFileContent("") + .setFileVersion(maxFileVersion + 1) + .setPreVersion(maxFileVersion) + .setFileNote("") + .setFileTime(timeStr) + .setFileSize(file.getSize()) + .setFilePath(parentFileInfo.getFilePath() + MYSQL_FILE_PATH_SPLIT + newEdFileInfo.getId()) + .setDataType(EleDataTypeEnum.FILE.code) + .setDataStatus(PublishEnum.PUBLISHED.getCode()) + .setEffectFlag(EffectFlagEnum.EFFECT.code) + .setFileCode(fileCode) + .setPrjDir(false); + this.baseMapper.insert(newEdFileInfo); + String fileDestPath = commonService.getFileSysPath(newEdFileInfo.getFileId()) + File.separator + mainName + suffix + "." + fileCode; + FileUtil.writeFromStream(file.getInputStream(), fileDestPath); + } else if (strategy == 3) { + // 文件名加”_1“,存为新文件 + EdFileInfo parentFileInfo = this.baseMapper.selectOne(Wrappers.lambdaQuery(EdFileInfo.class) + .eq(EdFileInfo::getId, parentId) + .eq(EdFileInfo::getEffectFlag, EffectFlagEnum.EFFECT.code)); + String codePathByDbPath = commonService.getCodePathByDbPath(parentFileInfo.getFilePath()); + EdFileInfo newEdFileInfo = new EdFileInfo(); + newEdFileInfo.newInit(); + String fileCode = commonService.createFileCode(codePathByDbPath, suffix, FILE_START_VERSION, newEdFileInfo.getFileTime()); + newEdFileInfo.setParentId(parentId) + .setFileCode(fileCode) + .setFileName(mainName + "_1") + .setFileType(suffix) + .setFileVersion(FILE_START_VERSION) + .setFileTime(newEdFileInfo.getFileTime()) + .setFileSize(file.getSize()) + .setFilePath(parentFileInfo.getFilePath() + MYSQL_FILE_PATH_SPLIT + newEdFileInfo.getId()) + .setDataType(EleDataTypeEnum.FILE.code) + .setDataStatus(PublishEnum.PUBLISHED.getCode()) + .setEffectFlag(EffectFlagEnum.EFFECT.code) + .setFileCode(fileCode) + .setPrjDir(false); + this.baseMapper.insert(newEdFileInfo); + String fileDestPath = commonService.getFileSysPath(parentFileInfo.getFileId()) + File.separator + mainName + "_1." + suffix + "." + fileCode; + FileUtil.writeFromStream(file.getInputStream(), fileDestPath); + } + + } + + + private String doSysFileMerge(String identifier, String fileName, Integer totalChunks) { + String currentUserId = UserThreadLocal.getUserId(); + for (int i = 1; i <= totalChunks; i++) { + String tmpPath = uploadDataDir + File.separator + currentUserId + identifier + File.separator + i + UPLOAD_FILE_CHUNK_SUFFIX; + if (!FileUtil.exist(new File(tmpPath))) { + String info = StrFormatter.format("第{}个分片没有上传完成,请上传完成后再合并。", i); + log.error(info); + throw new BizException(-1, info); + } + } + // 合并分片 + String destZipPath = uploadDataDir + File.separator + currentUserId + File.separator + identifier + File.separator + fileName; + File[] partFiles = FileUtil.ls(uploadDataDir + File.separator + currentUserId + File.separator + identifier); + + for (File partFile : partFiles) { + try (BufferedOutputStream outputStream = FileUtil.getOutputStream(destZipPath); + BufferedInputStream inputStream = FileUtil.getInputStream(partFile)) { + IoUtil.copy(inputStream, outputStream); + } catch (Exception e) { + FileUtil.del(destZipPath); + String info = "文件合并失败"; + log.error(info, e); + throw new BizException(-1, info); + } + } + Arrays.stream(partFiles).forEach(e -> FileUtil.del(e.getAbsolutePath())); + return destZipPath; + } } diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdPrjServiceImpl.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdPrjServiceImpl.java index 99cf88e..9ea77a9 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdPrjServiceImpl.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/EdPrjServiceImpl.java @@ -198,7 +198,6 @@ public class EdPrjServiceImpl extends ServiceImpl /** * 添加子集 - * * @param parentId * @param folderName * @return @@ -206,12 +205,13 @@ public class EdPrjServiceImpl extends ServiceImpl @Override @Transactional(rollbackFor = Exception.class) public ElectromagneticResult addFolder(String parentId, String folderName) { - return commonService.addFolder(parentId, folderName, true, true); + int id = Integer.parseInt(this.baseMapper.maxPrjId()); + String folderId = String.valueOf(id + 1); + return commonService.addFolder(parentId, folderName, true, true, folderId); } /** * 查询所有项目 - * * @return */ @Override diff --git a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/FileSystemServiceImpl.java b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/FileSystemServiceImpl.java index 2bc3ec6..cfe4c2a 100644 --- a/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/FileSystemServiceImpl.java +++ b/electrmangnetic/src/main/java/com/electromagnetic/industry/software/manage/service/serviceimpl/FileSystemServiceImpl.java @@ -25,6 +25,7 @@ public class FileSystemServiceImpl implements FileSystemService { @Override public void save(InputStream inputStream, String destination) { + FileUtil.writeFromStream(inputStream, destination); } @Override diff --git a/electrmangnetic/src/main/resources/application.properties b/electrmangnetic/src/main/resources/application.properties index a7b155a..b63fb91 100644 --- a/electrmangnetic/src/main/resources/application.properties +++ b/electrmangnetic/src/main/resources/application.properties @@ -13,8 +13,13 @@ spring.servlet.multipart.max-request-size=10MB pagehelper.helperDialect=mysql pagehelper.reasonable=false server.port=12395 +file.security.passwd=adknfhkj87654knd #windows文件存储目录,用于测试 -data.windows.path=E:/tmp/eleData/ -data.linux.path=/szsd/data/eleData +data.windows.path=D:/tmp/eleData/project/ +data.linux.path=/szsd/data/eleData/project/ +data.upload.windows.tmp.path=D:/tmp/eleData/upload/ +data.upload.linux.tmp.path=/szsd/data/eleData/upload/ +data.download.windows.tmp.path=D:/tmp/eleData/download/ +data.download.linux.tmp.path=/szsd/data/eleData/download/ prj.folder.max.length=6 diff --git a/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/cons/ElectromagneticConstants.java b/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/cons/ElectromagneticConstants.java index f07299c..c304a15 100644 --- a/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/cons/ElectromagneticConstants.java +++ b/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/cons/ElectromagneticConstants.java @@ -9,4 +9,6 @@ public interface ElectromagneticConstants { int FILE_START_VERSION = 100; String PRJ_PARENT_ID = "0"; + + String UPLOAD_FILE_CHUNK_SUFFIX = ".part"; } diff --git a/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/util/EleCommonUtil.java b/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/util/EleCommonUtil.java index bfd381c..d8ec8f8 100644 --- a/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/util/EleCommonUtil.java +++ b/electromagnetic-common/src/main/java/com/electromagnetic/industry/software/common/util/EleCommonUtil.java @@ -1,5 +1,7 @@ package com.electromagnetic.industry.software.common.util; +import cn.hutool.core.util.StrUtil; + import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.regex.Pattern; @@ -35,7 +37,7 @@ public final class EleCommonUtil { } public static boolean isFileNameValid(String fileFullName) { - if (fileFullName.length() > 32) { + if (StrUtil.isEmpty(fileFullName) || fileFullName.length() > 32) { return false; } return pattern.matcher(fileFullName).matches();