springboot+minio下载文件夹并压缩文件夹为zip(包含完整代码)

整体代码放在最后的
总体思路:
第一步:
读取这个文件夹的所有文件对象
这里主要时为了我们下一步递归准备参数

    /**bucketName为桶名称
    * folderPath为文件夹的在桶中路径
     */
 ListObjectsArgs listObjectsArgs=ListObjectsArgs.builder().bucket(bucketName).prefix(folderPath).build();

第二步:
递归查找文件对象
这里的思路为,遇到文件夹,就读取这个文件夹的所有文件对象,进入递归.遇到文件,将文件的objectName存放到list中,objectName就是文件路径.最终得到整个文件夹所有文件的路径的fileUrlList.

private List<String> findAndSaveFileList(ListObjectsArgs listObjectsArgs,String bucketName ) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        List<String> fileObjectsList =new ArrayList<>();
        Iterable<Result<Item>> results = coreClient.minioClient.listObjects(listObjectsArgs);
        for (Result<Item> result : results) {
            Item item = result.get();
            if (item.isDir()) {
                log.info("即将下载的文件路径:{}",item.objectName());
                ListObjectsArgs args = ListObjectsArgs.builder().bucket(bucketName).prefix(item.objectName()).build();
                List<String> list=findAndSaveFileList(args,bucketName);
                fileObjectsList.addAll(list);
            } else {
                fileObjectsList.add(item.objectName());
            }
        }
        return fileObjectsList;
    }

第三步:
准备文件输入流
根据第二步的文件路径的list,准备对应数量的文件输入流数组.然后遍历文件路径的list,去minio里面读取对应的文件输入流,将其放到文件输入流数组

InputStream[] srcFiles = new InputStream[fileUrlList.size()];
            //files name
            for (int i = 0; i < fileUrlList.size(); i++) {
                String fileUrl = fileUrlList.get(i);
                InputStream inputStream = coreClient.minioClient.getObject(GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileUrl)
                        .build());
                if (inputStream == null) {
                    continue;
                }
                log.info("正在下载文件:{}",fileUrlList.get(i));
                srcFiles[i] = inputStream;

            }

第四步
将文件输入流压缩,边压缩边返回
这里遍历文件输入流数组,准备压缩,压缩后的路径设置为第二步中的文件路径,这样压缩处理的文件路径和minio路径保持一致

response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("file.zip", "UTF-8"));
            ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());
            for (int i = 0; i < srcFiles.length; i++) {
                InputStream srcFile=srcFiles[i];
                String filePath=fileUrlList.get(i);
                log.info("正在压缩文件:{}",fileUrlList.get(i));
                compressFile(srcFile,filePath,zipOutputStream);
            }
            zipOutputStream.flush();
            zipOutputStream.close();

完整代码:

        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
        </dependency>
package cn.test.nvh.domain;


import cn.csdn.source.minio.config.MinIOClientConfig;
import io.minio.GetObjectArgs;
import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author: 
 * @description:
 * @date: 2024/9/27 16:30
 */
@Component
@Slf4j
public class download {
    @Autowired
    private MinIOClientConfig minIOClientConfig;
    private MinioClient minioClient;
    private MinioClient getCoreClient(){
        if(minioClient==null){
            minioClient=MinioClient.builder()
                    .endpoint(minIOClientConfig.getEndpoint())
                    .credentials(minIOClientConfig.getAccessKey(), minIOClientConfig.getSecretKey())
                    .build();

        }
        return minioClient;

    }
    
    public void downloadFolder(String folderPath, String bucketName, HttpServletResponse response) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        if(folderExists(folderPath,bucketName)) {
            ListObjectsArgs listObjectsArgs=ListObjectsArgs.builder().bucket(bucketName).prefix(folderPath).build();
            List<String> fileUrlList = findAndSaveFileList(listObjectsArgs,bucketName);
            //files InputStream
            InputStream[] srcFiles = new InputStream[fileUrlList.size()];
            //files name
            for (int i = 0; i < fileUrlList.size(); i++) {
                String fileUrl = fileUrlList.get(i);
                InputStream inputStream = getCoreClient().getObject(GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileUrl)
                        .build());
                if (inputStream == null) {
                    continue;
                }
                log.info("正在下载文件:{}",fileUrlList.get(i));
                srcFiles[i] = inputStream;

            }

            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("file.zip", "UTF-8"));
            ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());
            for (int i = 0; i < srcFiles.length; i++) {
                InputStream srcFile=srcFiles[i];
                String filePath=fileUrlList.get(i);
                log.info("正在压缩文件:{}",fileUrlList.get(i));
                compressFile(srcFile,filePath,zipOutputStream);
            }
            zipOutputStream.flush();
            zipOutputStream.close();
        }
    }


    public boolean folderExists(String folderPath,String bucketName) {
        ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
                .bucket(bucketName).prefix(folderPath)
                .recursive(false).build();
        Iterable<Result<Item>> iterable = getCoreClient().listObjects(listObjectsArgs);
        // 不为空则说明是文件夹
        return iterable.iterator().hasNext();
    }

    private List<String> findAndSaveFileList(ListObjectsArgs listObjectsArgs,String bucketName ) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        List<String> fileObjectsList =new ArrayList<>();
        Iterable<Result<Item>> results = getCoreClient().listObjects(listObjectsArgs);
        for (Result<Item> result : results) {
            Item item = result.get();
            if (item.isDir()) {
                log.info("即将下载的文件路径:{}",item.objectName());
                ListObjectsArgs args = ListObjectsArgs.builder().bucket(bucketName).prefix(item.objectName()).build();
                List<String> list=findAndSaveFileList(args,bucketName);
                fileObjectsList.addAll(list);
            } else {
                fileObjectsList.add(item.objectName());
            }
        }
        return fileObjectsList;
    }
    private void compressFile(InputStream inputStream,String path, ZipOutputStream zipOutputStream) throws IOException {
        try {
            ZipEntry ze = new ZipEntry(path);
            zipOutputStream.putNextEntry(ze);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) > 0) {
                zipOutputStream.write(buffer, 0, len);
            }

        }catch (Exception e){
            log.error(e.getMessage());
            log.error("读取文件失败");
        }
    }
}



请注意,minIOClientConfig为自己配置minio配置类,需要配置
endpoint
accessKey
secretKey
fileHost
等信息,这块根据用户自己的配置进行修改和配置,我这就不提供了
.最后感谢你的点赞和收藏!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值