From bfde5717d3d7484ce4c5df40537f42eef9f9865a Mon Sep 17 00:00:00 2001 From: mashuai Date: Fri, 17 Jan 2025 18:57:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bonus/common/biz/domain/FileInfo.java | 24 +++ .../com/bonus/common/biz/domain/HttpMsg.java | 22 +++ .../controller/ArchivesController.java | 4 +- .../archives/service/ArchivesService.java | 2 +- .../service/impl/ArchivesServiceImpl.java | 157 +++++++++++------- 5 files changed, 150 insertions(+), 59 deletions(-) create mode 100644 bonus-common-biz/src/main/java/com/bonus/common/biz/domain/HttpMsg.java diff --git a/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/FileInfo.java b/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/FileInfo.java index 06ade341..26e9c3aa 100644 --- a/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/FileInfo.java +++ b/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/FileInfo.java @@ -1,7 +1,10 @@ package com.bonus.common.biz.domain; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.Date; + /** * 文件信息 * @Author ma_sh @@ -10,7 +13,28 @@ import lombok.Data; @Data public class FileInfo { + /** + * 文件名称 + */ private String fileName; + /** + * 文件路径 + */ private String filePath; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private Date updateTime; + + /** + * 文件类型 + */ + private String docType; } diff --git a/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/HttpMsg.java b/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/HttpMsg.java new file mode 100644 index 00000000..7086b575 --- /dev/null +++ b/bonus-common-biz/src/main/java/com/bonus/common/biz/domain/HttpMsg.java @@ -0,0 +1,22 @@ +package com.bonus.common.biz.domain; + +import lombok.Data; + +/** + * 返回http信息 + * @Author ma_sh + * @create 2025/1/17 17:07 + */ +@Data +public class HttpMsg { + + /** + * 返回信息 + */ + private String msg; + + /** + * 返回编码 + */ + private Integer code; +} diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/controller/ArchivesController.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/controller/ArchivesController.java index a91afb03..e985aa5b 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/controller/ArchivesController.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/controller/ArchivesController.java @@ -176,9 +176,9 @@ public class ArchivesController extends BaseController { @PreventRepeatSubmit //@RequiresPermissions("archives:type:download") @GetMapping("/download") - public void download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) + public AjaxResult download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) { - archivesService.download(archivesVo, request, response); + return archivesService.download(archivesVo, request, response); } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/ArchivesService.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/ArchivesService.java index ece8a043..bb6aa936 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/ArchivesService.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/ArchivesService.java @@ -81,7 +81,7 @@ public interface ArchivesService { * @param response * @return */ - void download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response); + AjaxResult download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response); /** * 更新电子档案电子签名 diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/impl/ArchivesServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/impl/ArchivesServiceImpl.java index 38a8d000..b2241e88 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/impl/ArchivesServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/service/impl/ArchivesServiceImpl.java @@ -4,9 +4,11 @@ import cn.hutool.core.collection.CollectionUtil; import com.bonus.common.biz.config.DateTimeHelper; import com.bonus.common.biz.config.FileCompressor; import com.bonus.common.biz.domain.FileInfo; +import com.bonus.common.biz.domain.HttpMsg; import com.bonus.common.biz.domain.TreeBuild; import com.bonus.common.biz.domain.TreeNode; import com.bonus.common.biz.enums.HttpCodeEnum; +import com.bonus.common.core.exception.ServiceException; import com.bonus.common.core.utils.DateUtils; import com.bonus.common.core.utils.StringUtils; import com.bonus.common.core.web.domain.AjaxResult; @@ -29,11 +31,13 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.*; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -154,23 +158,25 @@ public class ArchivesServiceImpl implements ArchivesService { List list = archivesMapper.selectDetailsList(archivesDetails); if (CollectionUtils.isNotEmpty(list)) { for (ArchivesDetails details : list) { - if ((StringUtils.isNotBlank(details.getDocUrl()) && details.getDocUrl().startsWith("http")) && StringUtils.isNotBlank(details.getDocName())) { - String originalPath = details.getDocName(); - // 找到最后一个 '/' 字符的位置 - int lastSlashIndex = originalPath.lastIndexOf('/'); - // 从最后一个 '/' 字符之后提取文件名 - String fileName = originalPath.substring(lastSlashIndex + 1); - // 找到 '.png' 的位置 - int dotIndex = fileName.lastIndexOf('.'); - // 找到倒数第二个 '_' 的位置 - int underscoreIndex = fileName.lastIndexOf('_', dotIndex - 1); - // 截取文件名部分(不包含后缀和多余部分) - String namePart = fileName.substring(0, underscoreIndex); - // 截取后缀部分 - String suffix = fileName.substring(dotIndex); - // 拼接最终的文件名 - String extractedFileName = namePart + suffix; - details.setDocName(extractedFileName); + if ((StringUtils.isNotBlank(details.getDocUrl())) && StringUtils.isNotBlank(details.getDocName())) { + if (details.getDocUrl().startsWith("http") && details.getUpdateBy() == null) { + String originalPath = details.getDocName(); + // 找到最后一个 '/' 字符的位置 + int lastSlashIndex = originalPath.lastIndexOf('/'); + // 从最后一个 '/' 字符之后提取文件名 + String fileName = originalPath.substring(lastSlashIndex + 1); + // 找到 '.png' 的位置 + int dotIndex = fileName.lastIndexOf('.'); + // 找到倒数第二个 '_' 的位置 + int underscoreIndex = fileName.lastIndexOf('_', dotIndex - 1); + // 截取文件名部分(不包含后缀和多余部分) + String namePart = fileName.substring(0, underscoreIndex); + // 截取后缀部分 + String suffix = fileName.substring(dotIndex); + // 拼接最终的文件名 + String extractedFileName = namePart + suffix; + details.setDocName(extractedFileName); + } } } } @@ -298,65 +304,93 @@ public class ArchivesServiceImpl implements ArchivesService { * @return */ @Override - public void download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) { + public AjaxResult download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) { String zipSavePath = "D:/" + DateTimeHelper.getNowDate() + ".zip"; List idList = new ArrayList<>(); String[] arr = archivesVo.getIds().split(","); - Integer size = arr.length; - for(int i = 0; i list = archivesMapper.selectDetails(archivesVo.getDetailsIdList()); + if (CollectionUtils.isNotEmpty(list)) { + for (ArchivesDetails archivesDetails : list) { + if ("文件夹".equals(archivesDetails.getDocType())) { + HttpMsg httpMsg = new HttpMsg(); + httpMsg.setCode(500); + httpMsg.setMsg("所选文件中包含文件夹,文件夹不能下载!"); + return AjaxResult.error("所选文件中包含文件夹,文件夹不能下载!", httpMsg); + } + } + } try { File file=new File(zipSavePath); - if(!file.isDirectory() && !file.exists()){ + if(!file.isDirectory() && !file.exists()) { file.createNewFile(); } - // 根据id查询详情 - List list = archivesMapper.selectDetails(archivesVo.getDetailsIdList()); // 提取文件信息 List fileInfos = extractFileInfos(list); if (fileInfos.isEmpty()) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No files found to download."); - return; + return AjaxResult.error("未查询到文件信息,请检查后重新提交!"); } ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipSavePath)); for (FileInfo fileInfo : fileInfos) { String fileUrl = fileInfo.getFilePath(); String originalPath = fileInfo.getFileName(); - // 找到最后一个 '/' 字符的位置 - int lastSlashIndex = originalPath.lastIndexOf('/'); - // 从最后一个 '/' 字符之后提取文件名 - String fileName = originalPath.substring(lastSlashIndex + 1); - // 找到 '.png' 的位置 - int dotIndex = fileName.lastIndexOf('.'); - // 找到倒数第二个 '_' 的位置 - int underscoreIndex = fileName.lastIndexOf('_', dotIndex - 1); - // 截取文件名部分(不包含后缀和多余部分) - String namePart = fileName.substring(0, underscoreIndex); - // 截取后缀部分 - String suffix = fileName.substring(dotIndex); - // 拼接最终的文件名 - String extractedFileName = namePart + suffix; - String savePath = "D:/" + extractedFileName; - // 检查文件保存路径是否可写 + if (fileInfo.getUpdateBy() == null) { + // 找到最后一个 '/' 字符的位置 + int lastSlashIndex = originalPath.lastIndexOf('/'); + // 从最后一个 '/' 字符之后提取文件名 + String fileName = originalPath.substring(lastSlashIndex + 1); + // 找到 '.png' 的位置 + int dotIndex = fileName.lastIndexOf('.'); + // 找到倒数第二个 '_' 的位置 + int underscoreIndex = fileName.lastIndexOf('_', dotIndex - 1); + // 截取文件名部分(不包含后缀和多余部分) + String namePart = fileName.substring(0, underscoreIndex); + // 截取后缀部分 + String suffix = fileName.substring(dotIndex); + // 拼接最终的文件名 + originalPath = namePart + suffix; + } + if (!isValidFileExtension(originalPath)) { + // 可以根据业务需求添加默认文件类型或进行其他处理 + if (originalPath.lastIndexOf('.') == -1) { + originalPath = originalPath + "." + fileInfo.getDocType(); + } else { + originalPath = originalPath + fileInfo.getDocType(); + } + } + String savePath = "D:/" + originalPath; + // 获取 Path 对象 Path path = Paths.get(savePath); - if (Files.isWritable(path.getParent())) { - // 下载文件并保存到本地 - downloadFile(fileUrl, savePath); - // 将文件添加到压缩包 - fileToZip(savePath, fileName, zipOut); - // 将临时文件删除 - new File(savePath).delete(); - } else { - System.err.println("保存文件的路径不可写: " + savePath); + try { + // 确保父目录存在,如果不存在则创建 + if (!Files.exists(path.getParent())) { + Files.createDirectories(path.getParent()); + } + // 检查文件保存路径是否可写 + if (Files.isWritable(path.getParent())) { + // 下载文件并保存到本地 + downloadFile(fileUrl, savePath); + // 将文件添加到压缩包 + fileToZip(savePath, zipOut); + // 将临时文件删除 + new File(savePath).delete(); + } else { + System.err.println("保存文件的路径不可写: " + savePath); + } + } catch (IOException e) { + System.err.println("文件操作过程中出现异常: " + e.getMessage()); } } // 压缩完成后,关闭压缩流 zipOut.close(); //拼接下载默认名称并转为ISO-8859-1格式 String fileName = new String((DateTimeHelper.getNowDate() + "下载文件.zip").getBytes(),"ISO-8859-1"); - response.setHeader("Content-Disposition", "attchment;filename="+fileName); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); //该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭 ServletOutputStream outputStream = response.getOutputStream(); FileInputStream inputStream = new FileInputStream(zipSavePath); @@ -367,11 +401,23 @@ public class ArchivesServiceImpl implements ArchivesService { //下载完成之后,删掉这个zip包 File fileTempZip = new File(zipSavePath); fileTempZip.delete(); + return AjaxResult.success("下载成功"); } catch (IOException e) { e.printStackTrace(); + return AjaxResult.error("发生内部错误,请联系管理员!"); } } + /** + * 判断文件扩展名是否在允许的范围内 + * @param originalPath + * @return + */ + private boolean isValidFileExtension(String originalPath) { + // 定义一个正则表达式,匹配常见的文件扩展名 + String regex = ".*\\.(png|pdf|jpg|jpeg|txt|docx|xlsx|xls|ppt|pptx|zip)$"; + return Pattern.matches(regex, originalPath); + } /** * 下载文件 @@ -422,17 +468,13 @@ public class ArchivesServiceImpl implements ArchivesService { } } - public static void main(String[] args) { - System.out.println(System.getProperty("user.home") + File.separator + "test.txt"); - } /** * 将文件添加到压缩包 * @param filePath - * @param name * @param zipOut * @throws IOException */ - public static void fileToZip(String filePath,String name,ZipOutputStream zipOut) throws IOException { + public static void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException { // 需要压缩的文件 File file = new File(filePath); // 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName @@ -504,6 +546,9 @@ public class ArchivesServiceImpl implements ArchivesService { FileInfo fileInfo = new FileInfo(); fileInfo.setFileName(archivesDetails.getDocName()); fileInfo.setFilePath(archivesDetails.getDocUrl()); + fileInfo.setUpdateBy(archivesDetails.getUpdateBy()); + fileInfo.setUpdateTime(archivesDetails.getUpdateTime()); + fileInfo.setDocType(archivesDetails.getDocType()); fileInfos.add(fileInfo); } }