Java下载多个文件打成压缩包返回输出流,并解决被JVM占用无法打开

本文涉及的产品
对象存储 OSS,OSS 加速器 50 GB 1个月
简介: Java下载多个文件打成压缩包返回输出流,并解决被JVM占用无法打开

需求


给前端提供一个接口,可下载文件,如果只是一个文件就直接返回输出流,如果多个就打成一个压缩包返回输出流


参考代码


代码根据自己的业务逻辑进行修改!


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;
    }

调试效果

image.png

image.png

解压缩之后

image.png

解决文件被JVM占用无法打开

image.png


排查代码发现,流都关了,还是会出现这个问题,只能强制使用gc了

image.png

相关实践学习
对象存储OSS快速上手——如何使用ossbrowser
本实验是对象存储OSS入门级实验。通过本实验,用户可学会如何用对象OSS的插件,进行简单的数据存、查、删等操作。
目录
相关文章
|
4月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
235 1
|
6月前
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
500 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
|
7月前
|
监控 Java API
Java语言按文件创建日期排序及获取最新文件的技术
这段代码实现了文件创建时间的读取、文件列表的获取与排序以及获取最新文件的需求。它具备良好的效率和可读性,对于绝大多数处理文件属性相关的需求来说足够健壮。在实际应用中,根据具体情况,可能还需要进一步处理如访问权限不足、文件系统不支持某些属性等边界情况。
364 14
|
7月前
|
存储 运维 Kubernetes
Java启动参数JVM_OPTS="-Xms512m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError"
本文介绍了Java虚拟机(JVM)常用启动参数配置,包括设置初始堆内存(-Xms512m)、最大堆内存(-Xmx1024m)及内存溢出时生成堆转储文件(-XX:+HeapDumpOnOutOfMemoryError),用于性能调优与故障排查。
679 0
|
7月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
209 0
|
8月前
|
存储 Java 数据安全/隐私保护
Java技术栈揭秘:Base64加密和解密文件的实战案例
以上就是我们今天关于Java实现Base64编码和解码的实战案例介绍。希望能对你有所帮助。还有更多知识等待你去探索和学习,让我们一同努力,继续前行!
566 5
|
7月前
|
存储 人工智能 Java
java之通过Http下载文件
本文介绍了使用Java实现通过文件链接下载文件到本地的方法,主要涉及URL、HttpURLConnection及输入输出流的操作。
539 0
|
8月前
|
网络协议 安全 Java
实现Java语言的文件断点续传功能的技术方案。
像这样,我们就完成了一项看似高科技、实则亲民的小工程。这样的技术实现不仅具备实用性,也能在面对网络不稳定的挑战时,稳稳地、不失乐趣地完成工作。
470 0
|
存储 Java Windows
Java21 JDK下载安装及Windows环境变量配置
JDK是Java的开发工具包,要进行Java学习或开发之前,需先下载安装,下载地址如下:提示:这网址里面有三个扩展名的文件,分别是“.zip”、“.exe”和“.msi”,鄙人选择的是.exe的文件,下方的安装和环境的配置也是安装该文件的安装程序进行的。
3176 2
|
Oracle Java 关系型数据库
java17的下载与安装
java17的下载与安装
2609 0