From 85207c254d5f04fb0c39ebe79c9a824c827be024 Mon Sep 17 00:00:00 2001 From: mashuai Date: Tue, 14 Jan 2025 18:47:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ArchivesController.java | 4 +- .../archives/domain/ArchivesDetails.java | 3 +- .../material/archives/domain/ArchivesVo.java | 2 + .../service/impl/ArchivesServiceImpl.java | 265 +++++++++++++++++- .../material/back/domain/vo/MaCodeVo.java | 8 + .../impl/BackApplyInfoServiceImpl.java | 2 + .../material/back/BackApplyInfoMapper.xml | 4 +- 7 files changed, 273 insertions(+), 15 deletions(-) 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 1186a27f..74b7b325 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 @@ -175,8 +175,8 @@ public class ArchivesController extends BaseController { @ApiOperation(value = "下载电子档案右侧详情") @PreventRepeatSubmit //@RequiresPermissions("archives:type:download") - @PostMapping("/download") - public void download(@RequestBody ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) + @GetMapping("/download") + public void download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) { archivesService.download(archivesVo, request, response); } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesDetails.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesDetails.java index 51ceb936..0c924f8c 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesDetails.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesDetails.java @@ -40,8 +40,7 @@ public class ArchivesDetails extends BaseEntity { private String docSize; @ApiModelProperty(value = "年度") - @JsonFormat(pattern = "yyyy") - private Date year; + private String year; @ApiModelProperty(value = "机具类型id") private Long typeId; diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesVo.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesVo.java index ee1e6b69..ce4234d0 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesVo.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/archives/domain/ArchivesVo.java @@ -17,4 +17,6 @@ public class ArchivesVo { private List archivesDetailsList; private List detailsIdList; + + private String ids; } 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 76ff3d16..50408395 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 @@ -1,6 +1,7 @@ package com.bonus.material.archives.service.impl; 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.TreeBuild; @@ -18,18 +19,23 @@ import com.bonus.material.archives.mapper.ArchivesMapper; import com.bonus.material.archives.service.ArchivesService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.tomcat.util.http.fileupload.IOUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; +import java.net.*; 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.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * 电子档案管理接口实现类 @@ -43,6 +49,10 @@ public class ArchivesServiceImpl implements ArchivesService { @Resource private ArchivesMapper archivesMapper; + private static final String DOMAIN = "http://127.0.0.1:9300"; + private static final String PATH = "/usr/local/bonus/uploadPath"; + private static final String PREFIX = "/statics"; + /** * 获取电子档案分类树 * @param archiveInfo @@ -145,7 +155,8 @@ public class ArchivesServiceImpl implements ArchivesService { */ @Override public List getDetailsList(ArchivesDetails archivesDetails) { - return archivesMapper.selectDetailsList(archivesDetails); + List list = archivesMapper.selectDetailsList(archivesDetails); + return list; } /** @@ -261,14 +272,133 @@ public class ArchivesServiceImpl implements ArchivesService { return AjaxResult.error(HttpCodeEnum.TO_PARAM_NULL.getCode(), HttpCodeEnum.TO_PARAM_NULL.getMsg()); } + /*@Override + public void download(ArchivesVo archivesVo, HttpServletRequest request, HttpServletResponse response) { + List idList = new ArrayList<>(); + String[] arr = archivesVo.getIds().split(","); + Integer size = arr.length; + for (int i = 0; i < size; i++) { + idList.add(Long.valueOf(arr[i])); + } + archivesVo.setDetailsIdList(idList); + // 根据id查询详情 + List list = archivesMapper.selectDetails(archivesVo.getDetailsIdList()); + // 提取文件信息 + List fileInfos = extractFileInfos(list); + //如果有附件 进行zip处理 + String zipFileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".zip"; + // 设置响应头 + response.setContentType("application/zip"); + response.setHeader("Content-Disposition", "attachment; filename=" + zipFileName); + if (fileInfos != null && fileInfos.size() > 0) { + *//*try { + //被压缩文件流集合 + InputStream[] srcFiles = new InputStream[fileInfos.size()]; + //被压缩文件名称 + String[] srcFileNames = new String[fileInfos.size()]; + for (FileInfo entity : fileInfos) { + //以下代码为获取图片inputStream + InputStream ins = ossService.getObject(OssConfiguration.bucket, entity.getObjectKey()); + if (ins == null) { + continue; + } + //塞入流数组中 + srcFiles[i] = ins; + srcFileNames[i] = entity.getFileName(); + i++; + } + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("下载.zip", "UTF-8")); + //多个文件压缩成压缩包返回 + ZipUtil.zip(response.getOutputStream(), srcFileNames, srcFiles); + } catch (IOException e) { + e.printStackTrace(); + }*//* + // 创建 MinIO 客户端 + String bucketName = "bonus"; + String endpoint = "http://192.168.0.14:9090"; + String accessKey = "QAxpqXEVc9VEQQ4H3sOn"; + String secretKey = "3oTv7oAN9G7zhUoMW1ii3fv4pdkl8PcmJuxU50O6"; + + // 检查存储桶是否存在,如果不存在则创建 + try { + // 创建 MinIO 客户端 + MinioClient minioClient = MinioClient.builder() + .endpoint(endpoint) + .credentials(accessKey, secretKey) + .build(); + + // 检查存储桶是否存在,如果不存在则创建 + boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); + if (!found) { + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); + } + + // 创建 ZipOutputStream 用于生成压缩包 + try (ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFileName)))) { + // 假设你有一个文件列表,这里可以从 MinIO 中获取文件列表,例如列出存储桶中的所有文件 + // 以下是一个示例,列出存储桶中的所有对象 + // List> objects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build()); + // 为了简化,假设我们已经有一个文件列表,存储在一个字符串数组中 + String[] objectKeys = {"file1.txt", "file2.txt", "file3.txt"}; + for (String objectKey : objectKeys) { + // 获取文件的输入流 + try (InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectKey).build()); + BufferedInputStream bis = new BufferedInputStream(inputStream)) { + // 创建一个 ZipEntry 并将其添加到 ZipOutputStream 中 + ZipEntry zipEntry = new ZipEntry(objectKey); + zipOut.putNextEntry(zipEntry); + + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = bis.read(buffer)) != -1) { + zipOut.write(buffer, 0, bytesRead); + } + // 关闭当前的 ZipEntry + zipOut.closeEntry(); + } catch (IOException e) { + System.err.println("Error reading file from MinIO: " + objectKey); + e.printStackTrace(); + } + } + } catch (IOException e) { + System.err.println("Error creating zip file: " + zipFileName); + e.printStackTrace(); + } + } catch (MinioException e) { + System.err.println("Error with MinIO client: " + e.getMessage()); + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } + } + }*/ + /** * 下载电子档案右侧详情 * @param archivesVo + * * @return */ @Override public void 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()); // 提取文件信息 @@ -277,19 +407,134 @@ public class ArchivesServiceImpl implements ArchivesService { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No files found to download."); return; } - // 创建临时ZIP文件路径 - String zipFilePath = createTempZipFile(fileInfos); - // 设置响应头 - setResponseHeaders(response); - // 将ZIP文件流返回给客户端 - sendZipFileToClient(zipFilePath, response); - // 删除临时文件 - deleteTempZipFile(zipFilePath); + 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; + // 检查文件保存路径是否可写 + 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); + } + } + // 压缩完成后,关闭压缩流 + zipOut.close(); + //拼接下载默认名称并转为ISO-8859-1格式 + String fileName = new String((DateTimeHelper.getNowDate() + "下载文件.zip").getBytes(),"ISO-8859-1"); + response.setHeader("Content-Disposition", "attchment;filename="+fileName); + //该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭 + ServletOutputStream outputStream = response.getOutputStream(); + FileInputStream inputStream = new FileInputStream(zipSavePath); + // copy方法为文件复制,在这里直接实现了下载效果 + IOUtils.copy(inputStream, outputStream); + // 关闭输入流 + inputStream.close(); + //下载完成之后,删掉这个zip包 + File fileTempZip = new File(zipSavePath); + //fileTempZip.delete(); } catch (IOException e) { e.printStackTrace(); } } + + /** + * 下载文件 + * @param fileUrl + * @param savePath + */ + private void downloadFile(String fileUrl, String savePath) throws IOException { + URL url = new URL(fileUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + // 设置请求方法为 GET + connection.setRequestMethod("GET"); + // 以下是一些可能的请求头设置,根据服务器需求修改 + connection.setRequestProperty("User-Agent", "Mozilla/5.0"); + connection.setRequestProperty("Accept", "application/pdf,text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); + connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); + // 禁用缓存 + connection.setRequestProperty("Cache-Control", "no-cache"); + connection.setRequestProperty("Pragma", "no-cache"); + // 假设需要添加认证信息,添加 Authorization 头,根据实际情况修改 + connection.setRequestProperty("Authorization", "Bearer your_access_token"); + // 延长连接超时和读取超时时间 + connection.setConnectTimeout(50000); + connection.setReadTimeout(50000); + try { + int responseCode = connection.getResponseCode(); + if (responseCode == 200) { + try (InputStream inputStream = connection.getInputStream(); + BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); + FileOutputStream fileOutputStream = new FileOutputStream(savePath)) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = bufferedInputStream.read(buffer))!= -1) { + fileOutputStream.write(buffer, 0, bytesRead); + } + } + } else { + throw new IOException("Server returned HTTP response code: " + responseCode); + } + } catch (IOException e) { + // 更详细的异常信息打印 + System.err.println("Failed to download file from " + fileUrl); + } finally { + connection.disconnect(); + } + } + + /** + * 将文件添加到压缩包 + * @param filePath + * @param name + * @param zipOut + * @throws IOException + */ + public static void fileToZip(String filePath,String name,ZipOutputStream zipOut) throws IOException { + // 需要压缩的文件 + File file = new File(filePath); + // 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName + String fileName = file.getName(); + FileInputStream fileInput = new FileInputStream(filePath); + // 缓冲 + byte[] bufferArea = new byte[1024 * 10]; + BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10); + // 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称 + zipOut.putNextEntry(new ZipEntry(fileName)); + int length = 0; + // 最常规IO操作,不必紧张 + while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) { + zipOut.write(bufferArea, 0, length); + } + //关闭流 + fileInput.close(); + // 需要注意的是缓冲流必须要关闭流,否则输出无效 + bufferStream.close(); + // 压缩流不必关闭,使用完后再关 + } + /** * 电子签名 修改用户表信息 * @param info @@ -360,7 +605,7 @@ public class ArchivesServiceImpl implements ArchivesService { FileCompressor.zipFiles(fileInfos, tempZipFilePath); } catch (IOException e) { throw new IOException("Error creating ZIP file", e); - } + } return tempZipFilePath; } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/domain/vo/MaCodeVo.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/domain/vo/MaCodeVo.java index 96701a49..b50e4208 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/domain/vo/MaCodeVo.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/domain/vo/MaCodeVo.java @@ -1,8 +1,11 @@ package com.bonus.material.back.domain.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.Date; + /** * @Author ma_sh * @create 2024/11/11 18:30 @@ -53,4 +56,9 @@ public class MaCodeVo { @ApiModelProperty(value = "协议ID") private Long agreementId; + + private String createBy; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/service/impl/BackApplyInfoServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/service/impl/BackApplyInfoServiceImpl.java index 65cca78d..cfb38bed 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/service/impl/BackApplyInfoServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/back/service/impl/BackApplyInfoServiceImpl.java @@ -1020,6 +1020,8 @@ public class BackApplyInfoServiceImpl implements IBackApplyInfoService { maCodeDto.setTypeId(maCodeVo.getTypeId()); maCodeDto.setMaStatus(maCodeVo.getMaStatus()); maCodeDto.setMaterialType(maCodeVo.getMaterialType()); + maCodeDto.setCreateBy(maCodeVo.getCreateBy()); + maCodeDto.setCreateTime(maCodeVo.getCreateTime()); // 查询并设置编码附件 List bmFileInfoList = fetchBmFileInfos(backApplyInfo.getId(), maCodeVo.getMaId()); if (CollectionUtils.isNotEmpty(bmFileInfoList)) { diff --git a/bonus-modules/bonus-material/src/main/resources/mapper/material/back/BackApplyInfoMapper.xml b/bonus-modules/bonus-material/src/main/resources/mapper/material/back/BackApplyInfoMapper.xml index f86e9441..8b9e1b6d 100644 --- a/bonus-modules/bonus-material/src/main/resources/mapper/material/back/BackApplyInfoMapper.xml +++ b/bonus-modules/bonus-material/src/main/resources/mapper/material/back/BackApplyInfoMapper.xml @@ -361,7 +361,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" mt.type_name AS materialName, mt1.type_name AS typeName, bcd.ap_detection AS apDetection, - mm.ma_status AS maStatus + mm.ma_status AS maStatus, + bcd.create_time AS createTime, + bcd.create_by AS createBy FROM back_check_details bcd left join ma_machine mm on bcd.ma_id = mm.ma_id