java 批量下载将多个文件(minio中存储)压缩成一个zip包

这篇具有很好参考价值的文章主要介绍了java 批量下载将多个文件(minio中存储)压缩成一个zip包。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我的需求是将minio中存储的文件按照查询条件查询出来统一压成一个zip包然后下载下来。

思路:针对这个需求,其实可以有多个思路,不过也大同小异,一般都是后端返回流文件前端再处理下载,也有少数是压缩成zip包之后直接给下载链接返回到前端,前端收到链接url直接window.open()进行下载,不过这种下载zip包的路径要确保是在网站下,否则访问不到,还有一个缺点就是文件没法删除,占用存储空间,后期需人为动作清理,选择哪种思路就可以看具体需求啦,我选择的是第一种思路,以下就针对第一种后端返回流方式进行具体介绍。

首先说第一种方法:将需要下载的文件找到,minio中有查询方法将文件转成inputStream,这里就不多说了,拿到一组InputStream,我们就可以写入一个zip包里了,创建临时zip路径,将流遍历写入文件,读取临时zip文件再写入response中的outputStream,最后删除临时文件。

前端处理方法最后统一介绍,后端核心代码如下:

public void downloadZip(String name, List<MediaFileEntity> filePaths,HttpServletResponse     response){
        File zipFile = compressedFileToZip(name,filePaths);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            FileInputStream ins = new FileInputStream(zipFile);
            WritableByteChannel writableByteChannel = Channels.newChannel(os);
            FileChannel fileChannel = ins.getChannel();
            fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
            fileChannel.close();
            response.setCharacterEncoding("UTF-8");
            name = URLEncoder.encode(name, "UTF-8");
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(name.getBytes("iso8859-1")));
            response.setContentLength(os.size());
            response.setHeader("filename", name);
            response.addHeader("Content-Length", "" + os.size());
            var outputstream = response.getOutputStream();
            os.writeTo(outputstream);
            os.flush();
            os.close();
            outputstream.flush();
            outputstream.close();
            writableByteChannel.close();
            if(zipFile.exists()){
                //删除临时文件
                zipFile.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 构建临时zip文件
     **/
    public File compressedFileToZip(String name, List<MediaFileEntity> mediaFileEntityList) {
        String zipName = name.concat(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))).concat(".zip");
        //临时zip路径
        String fileZipPath = System.getProperty("user.dir").concat("/").concat(zipName);
        OutputStream os = null;
        ZipOutputStream zos = null;
        File file = new File(fileZipPath);
        try {
            if(!file.exists()){
                file.createNewFile();
            }
            os= new FileOutputStream(file);
            zos = new ZipOutputStream(os) ;
            for (MediaFileEntity entity:mediaFileEntityList
                 ) {
                zos.putNextEntry(new ZipEntry(entity.getFileName()));
                //minio 获取流
                InputStream ins = ossService.getObject(OssConfiguration.bucket,entity.getObjectKey());
                FileInputStream insf=convertToFileInputStream(ins);
                WritableByteChannel writableByteChannel = Channels.newChannel(zos);
                FileChannel fileChannel = insf.getChannel();
                fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
                zos.closeEntry();
                fileChannel.close();
                ins.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

第二种方法:安装hutool依赖,调用hutool包中的ZipUtil工具类中的zip方法进行下载,。此方法需要有3个参数,分别是OutoutStream,每个流对应的文件名字符串数组,文件的InputStream数组。

java 批量下载将多个文件(minio中存储)压缩成一个zip包,java,vue.js,javascript,spring boot

首先将需要下载的文件找到,拿到一组InputStream,也就是zip方法中的第3个参数,第一个参数顾名思义就是你想要输出的地方,我们是返回给前端所以就是response.getOutputStream(),第二个参数我们遍历文件时也可以拿到,废话不多说了,上代码看吧。

在项目下安装hutool依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.7</version>
</dependency>
  /**
     * 下载多个文件转zip压缩包
     *
     * @param mediaFileEntityList
     * @param response
     * @throws Exception
     */
    public void dowloadToZip(List<MediaFileEntity> mediaFileEntityList, HttpServletResponse response) throws Exception {

        int i = 0;
        //如果有附件 进行zip处理
        if (mediaFileEntityList != null && mediaFileEntityList.size() > 0) {
            try {
                //被压缩文件流集合
                InputStream[] srcFiles = new InputStream[mediaFileEntityList.size()];
                //被压缩文件名称
                String[] srcFileNames = new String[mediaFileEntityList.size()];
                for (MediaFileEntity entity : mediaFileEntityList) {
                    //以下代码为获取图片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();
            }
        }

    }

Controller这边可以直接写成没有返回值的接口,我的例子如下,仅供参考:

    @GetMapping("/{workspace_id}/fileDownList")
    @ApiOperation(value = "查询文件的下载地址")
    public void getFileStreamList(@PathVariable(name = "workspace_id") String workspaceId,
                                  @RequestParam(name = "ids") String ids, HttpServletResponse response) throws Exception {

        List<Integer> fileIds= Arrays.stream(ids.split(",")).collect(Collectors.toList()).stream()
                .map(Integer::parseInt)
                .collect(Collectors.toList());
        List<MediaFileEntity> mediaFileEntityList = fileService.getMediaListById(workspaceId, fileIds);
//        fileUtil.downloadZip("111",mediaFileEntityList,response);//第一种方法
        fileUtil.dowloadToZip(mediaFileEntityList,response);//第二种方法
    }

 到此,后端zip下载就完毕了,下面我们说说前端如何处理

网上查询前端处理大致都是如下,但是我自己使用的时候下载总是提示损坏,后找了一个工具类直接调用,就可以了,示例代码请求是get,如需调整,可根据情况自行调整

核心代码如下:

import { saveAs } from 'file-saver';    
const baseURL = (window as any).config.VITE_APP_BASE_API; //import.meta.env.VITE_APP_BASE_API;

export default {
zip(url: string, name: string) {
        url = baseURL + url;
        axios({
            method: 'get',
            url: url,
            responseType: 'blob',
            headers: { Authorization: 'Bearer ' + getToken() },
        }).then(res => {
            const isBlob = blobValidate(res.data);
            if (isBlob) {
                const blob = new Blob([res.data], { type: 'application/zip' });
                this.saveAs(blob, name);
            } else {
                this.printErrMsg(res.data);
            }
        });
    },
    saveAs(text: any, name: string, opts?: any) {
        saveAs(text, name, opts);
    },
    async printErrMsg(data: any) {
        const resText = await data.text();
        const rspObj = JSON.parse(resText);
        const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'];
        // ElMessage.error(errMsg);
    },
    blobValidate(data: any) {
        return data.type !== 'application/json';
    }
};

按钮绑定方法直接调用zip下载方法,传参为url和要导出zip的名称,示例如下:文章来源地址https://www.toymoban.com/news/detail-687186.html

import download from '@/plugins/download';

function batchDownload(){
    ElMessage.success("文件下载中,请勿重复点击!");
    download.zip(`/media/api/v1/files/${workspaceId}/fileDownList?ids=${selectlist.value.join(",")}`,"MediaFiles"+new Date().toLocaleDateString()+".zip")

}

到了这里,关于java 批量下载将多个文件(minio中存储)压缩成一个zip包的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java~将多个输出流压缩成一个zip文件

    hutool工具包可以帮我们完成这件事,几行代码可以实现,我们提供两种方式,压缩本地文件和压缩内存流。 扩展阅读:如果希望进行模版技术,可以看一下org.apache.velocity.tools:velocity-tools-generic包,可直接引用依赖 *版本 引用依赖 org.apache.velocity 是 Apache Velocity 模板引擎的 Ja

    2024年02月05日
    浏览(42)
  • Java实现打包压缩文件或文件夹生成zip以实现多文件批量下载

    有时候在系统中需要一次性下载多个文件,但逐个下载文件比较麻烦。这时候,最好的解决办法是将所有文件打包成一个压缩文件,然后下载这个压缩文件,这样就可以一次性获取所有所需的文件了。 下面是一个名为CompressUtil的工具类的代码,它提供了一些方法来处理文件压

    2024年02月06日
    浏览(58)
  • SpringBoot整合minio,文件的上传下载,批量获取

    Minio是GlusterFS创始人之一Anand Babu Periasamy发布新的开源项目。基于Apache License v2.0开源协议的对象存储项目,采用Golang实现,客户端支Java,Python,Javacript, Golang语言。 其设计的主要目标是作为私有云对象存储的标准方案。主要用于存储海量的图片,视频,文档等。非常适合于存储

    2024年02月12日
    浏览(48)
  • js 实现多个文件循环下载 批量下载

    最近业务涉及勾选之后多个word文件下载 开始用的循环方式 怎么试都是下载最后一个文件 后来找到原因是 当循环执行下载的时候,几个下载命令连续执行的时候,浏览器会取消上一个下载,直接下载最后一个文件 。所以要加一个定时器,让几个连续的下载请求之间有时间间

    2024年02月11日
    浏览(49)
  • 【分布式文件存储】MinIO部署及实现文件上传下载

    目录 概述 MinIO集群部署 准备docker-compose.yml 测试启动 MinIO用户管理 Buckets管理  创建Buckets MinIO客户端 引入依赖   文件上传下载Demo 调用API碰到的问题 MinIO | 高性能, Kubernetes 原生对象存储 MinIO是全球领先的对象存储先锋,目前在全世界有数百万的用户。 高性能 ,在标准硬件

    2024年02月07日
    浏览(59)
  • 详解JS实现单个或多个文件批量下载的方法

    目录 0.JS简介 前言 单个文件Download 方案一:location.href or window.open 方案二:通过a标签的download属性 方案三:API请求 多个文件批量Download 方案一:按单个文件download方式,循环依次下载 方案二:前端打包成zip download 方案三:后端压缩成zip,然后以文件流url形式,前端调用dow

    2024年02月01日
    浏览(58)
  • docker save多个镜像打包成一个tar.gz压缩文件

    有时候我们需要将docker中的多个镜像批量的传输到另一台机器,如果通过docker save这种命令则需要制作多个tar文件,这样以来冗余的操作较多而且tar文件占据的空间较大,不利于传输。 可以通过以下命令在两个docker之间实现多个镜像批量传输: 如果想将所有镜像传输到另一台

    2024年02月04日
    浏览(73)
  • 百度智能云对象存储BOS批量下载文件方法

    百度智能云对象存储BOS支持批量打包下载吗?目前对象存储BOS浏览器端不支持批量下载,可以使用对象存储BOS桌面或BOSCMD批量下载,也可以使用API/SDK调用接口循环下载。新手站长网来详细说下百度云对象存储BOS批量下载的方法: 目录 百度云对象存储BOS批量下载 BOS桌面客户端

    2023年04月20日
    浏览(38)
  • Java调用Elasticsearch API实现全文检索,搭配MinIO文件存储

    应用背景: 对存储在MinIO服务器的文件实现全文检索。也可以是其他服务器或本地文件,本文仅详细介绍MinIO文件的读取及转换。通过Elasticsearch的Ingest-Attachment插件抽取文件内容,支持Word、Excel、PDF、TXT等格式文件,无需手动解析文件内容。 上代码,详细解释可以阅读注释、

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包