需求
给前端提供一个接口,可下载文件,如果只是一个文件就直接返回输出流,如果多个就打成一个压缩包返回输出流
参考代码
代码根据自己的业务逻辑进行修改!
controller
```java /** * 打包下载文档 * @param signId */ @PostMapping("/downloadZip") @ApiOperationSupport(order = 5) @ApiOperation(value = "下载文档", notes = "传入signId") public R download(@ApiParam(value = "签署id", required = true) @RequestParam Long signId) throws Exception { return R.data(signDocumentService.downloadZipFile(signId).toString()); } ```
service
/** * 根据id查询签署附件打包并下载 * * @param signId * @return FileOutputStream * @throws Exception */ FileOutputStream downloadZipFile(Long signId) throws Exception;
serviceImpl
@Override public FileOutputStream downloadZipFile(Long signId) throws Exception { InputStream input = null; // 定义压缩输出流 ZipOutputStream zipOut = null; File zipFile = null; List<String> ossList = null; String path = null; String download = null; String localPath = null; try { ossList = new ArrayList(); // 根据signId查询签署文档 List<SignDocumentVO> signDocuments = signDocumentMapper.selectAttachs(signId); // 如果不为空 if (!signDocuments.isEmpty()) { // 如果只有一个签署文件就直接下载,如果有多个就打压缩包 if (signDocuments.size()==FILE_ONE.getCode()) { return downloadDetails(signId); }else{ for (SignDocument signDocument : signDocuments) { // 根据签署文档的attachId查询对应的附件 Attach attach = attachMapper.selectAttachById(signDocument.getAttachId()); String link = attach.getLink(); // 把oss文件下载到项目本地 path = SignDocumentServiceImpl.class.getClass().getResource("/").getPath() + FileUtil.getNameWithoutExtension(link) + "." + PDF; localPath = SignDocumentServiceImpl.class.getClass().getResource("/").getPath(); // 把获取到的oss文件链接下载到本地 download = download(link, path); ossList.add(download); // 定义压缩文件夹的名称和相关的位置 zipFile = new File(localPath + "file.zip"); // 实例化压缩输出流 并定制压缩文件的输出路径 zipOut = new ZipOutputStream(new FileOutputStream(zipFile)); } } } for (String o : ossList) { File file = new File(o); // 定义输入文件流 input = new FileInputStream(file); // 一个文件对对应一个ZipEntry实体 zipOut.putNextEntry(new ZipEntry(file.getName())); int readsize = 1024 * 1024 * 5; byte[] buf = new byte[readsize]; int temp = 0; while ((temp = input.read(buf)) != -1) { zipOut.write(buf, 0, temp); } } // 删除本地文件 // FileUtil.deleteQuietly(new File(path)); } catch (IOException e) { log.error("打包下载失败!", e); } finally { if(null != zipOut){ zipOut.closeEntry(); zipOut.close(); } if(null != input){ input.close(); } // 回收资源 System.gc(); } // 压缩包文件转为FileOutputStream FileOutputStream fileOutputStream = new FileOutputStream(String.valueOf(zipOut)); return fileOutputStream; } private FileOutputStream downloadDetails(Long signId) throws Exception { String path = null; String download = null; FileOutputStream fileOutputStream = null; // 根据signId查询签署文档 List<SignDocumentVO> signDocuments = signDocumentMapper.selectAttachs(signId); // 如果不为空 if (!signDocuments.isEmpty()) { for (SignDocument signDocument : signDocuments) { // 根据签署文档的attachId查询对应的附件 Attach attach = attachMapper.selectAttachById(signDocument.getAttachId()); String link = attach.getLink(); // 把oss文件下载到项目本地 path = SignDocumentServiceImpl.class.getClass().getResource("/").getPath() + FileUtil.getNameWithoutExtension(link) + "." + PDF; // 把获取到的oss文件链接下载到本地 download = download(link, path); File file = new File(download); fileOutputStream = new FileOutputStream(file); } } return fileOutputStream; }
调试效果
解压缩之后
解决文件被JVM占用无法打开
排查代码发现,流都关了,还是会出现这个问题,只能强制使用gc了