SpringBoot+Minio实现多文件下载和批量下载

在这里插入图片描述

文章目录

SpringBoot+minio实现多文件下载

1、SpringBoot+minio实现多文件打成一个压缩包下载

要在 Spring Boot 中使用 MinIO 实现多文件打包成一个压缩文件并下载,主要分为以下几个步骤:

  1. 连接 MinIO:创建 MinIO 客户端,用于与 MinIO 进行通信。
  2. 文件读取:从 MinIO 中读取多个文件。
  3. 文件压缩:将文件压缩为 ZIP 格式。
  4. 文件下载:将生成的 ZIP 文件流返回给客户端。
1. 添加依赖

如果还没有添加 MinIO 依赖,可以手动下载 MinIO 客户端库,或者直接用 Maven 来管理依赖:

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.3.5</version>
</dependency>
2. 配置 MinIO 客户端

application.properties 中添加 MinIO 配置:

minio.url=http://localhost:9000
minio.accessKey=your-access-key
minio.secretKey=your-secret-key
minio.bucketName=your-bucket

然后在 @Configuration 类中配置 MinIO 客户端:

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {
   

    @Value("${minio.url}")
    private String url;

    @Value("${minio.accessKey}")
    private String accessKey;

    @Value("${minio.secretKey}")
    private String secretKey;

    @Bean
    public MinioClient minioClient() {
   
        return MinioClient.builder()
                .endpoint(url)
                .credentials(accessKey, secretKey)
                .build();
    }
}
3. 创建下载和压缩逻辑

在服务类中添加下载和压缩方法,以下代码会将指定的文件列表压缩成一个 ZIP 并返回给客户端。

import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class MinioService {
   

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucketName}")
    private String bucketName;

    public void downloadFilesAsZip(List<String> fileNames, HttpServletResponse response) {
   
        try {
   
            // 设置响应头,文件名为 download.zip
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=download.zip");

            // 创建 ZIP 输出流
            try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
   
                for (String fileName : fileNames) {
   
                    // 获取每个文件的输入流
                    try (InputStream inputStream = minioClient.getObject(
                            GetObjectArgs.builder().bucket(bucketName).object(fileName).build())) {
   

                        // 创建 ZIP 文件条目
                        zipOut.putNextEntry(new ZipEntry(fileName));

                        // 将文件数据写入 ZIP
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = inputStream.read(buffer)) >= 0) {
   
                            zipOut.write(buffer, 0, length);
                        }
                        zipOut.closeEntry();  // 结束该条目的写入
                    }
                }
                zipOut.finish();  // 完成 ZIP 文件
            }
        } catch (Exception e) {
   
            throw new RuntimeException("Error occurred while downloading files as zip", e);
        }
    }
}
4. 创建控制器方法来触发下载

在控制器中定义一个方法,接收前端的请求并调用服务类进行压缩与下载。

@RestController
public class FileDownloadController {
   

    @Autowired
    private MinioService minioService;

    @GetMapping("/download-zip")
    public void downloadZip(@RequestParam List<String> fileNames, HttpServletResponse response) {
   
        minioService.downloadFilesAsZip(fileNames, response);
    }
}
5. 测试下载功能

现在可以通过 HTTP GET 请求测试该功能:

GET http://localhost:8080/download-zip?fileNames=file1.txt&fileNames=file2.jpg&fileNames=file3.pdf
注意事项
  • 内存消耗:如果文件较多或较大,生成 ZIP 文件的过程可能会占用大量内存。可以优化为逐个文件流写入 ZIP,避免内存问题。
  • 异常处理:可扩展异常处理,捕获 MinIO 连接失败、文件不存在等情况,并返回更详细的错误信息。

这个实现将从 MinIO 读取文件流,逐一压缩到 ZIP 中,并通过 HTTP 响应流返回给客户端。


2、在minio指定的桶名下面生产一个文件夹

SpringBoot+minio实现多文件下载时在minio指定的桶名下面生产一个文件夹,将需要下载放到这个文件夹中,并把这个文件夹打成一个压缩包后进行下载,下载成功后删除这个文件夹

在使用 Spring Boot 和 MinIO 实现上述功能时,可以按以下步骤操作:

  1. 创建 MinIO 文件夹:在 MinIO 指定的桶内创建一个文件夹。
  2. 上传文件到文件夹:将需要下载的文件复制到该文件夹。
  3. 打包文件夹为 ZIP 并下载:将文件夹内的文件打包为 ZIP 文件并返回给客户端。
  4. 清理文件夹:下载成功后,删除 MinIO 上的文件夹及其内容。

以下是实现的详细步骤和代码。

1. MinIO 配置

确保 MinIO 客户端配置正确。使用 application.properties 配置 MinIO 相关信息。

minio.url=http://localhost:9000
minio.accessKey=your-access-key
minio.secretKey=your-secret-key
minio.bucketName=your-bucket

并创建 MinIO 客户端配置类:

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {
   

    @Value("${minio.url}")
    private String url;

    @Value("${minio.accessKey}")
    private String accessKey;

    @Value("${minio.secretKey}")
    private String secretKey;

    @Bean
    public MinioClient minioClient() {
   
        return MinioClient.builder()
                .endpoint(url)
                .credentials(accessKey, secretKey)
                .build();
    }
}
2. 编写业务逻辑

在服务类中添加方法来实现各步骤。

文件夹操作和压缩下载
import io.minio.CopyObjectArgs;
import io.minio.MinioClient;
import io.minio.RemoveObjectArgs;
import io.minio.GetObjectArgs;
import io.minio.ObjectWriteResponse;
import io.minio.UploadObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class MinioService {
   

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucketName}")
    private String bucketName;

    // 将需要下载的文件放入临时文件夹并压缩下载
    public void downloadFolderAsZip(List<String> fileNames, HttpServletResponse response) {
   
        String tempFolderName = "temp-folder-" + UUID.randomUUID();  // 随机生成临时文件夹名称

        try {
   
            // 上传文件到临时文件夹
            for (String fileName : fileNames) {
   
                String objectName = tempFolderName + "/" + fileName;

                // 复制原始文件到临时文件夹
                minioClient.copyObject(
                        CopyObjectArgs.builder()
                                .bucket(bucketName)
                                .object(objectName)
                                .source(bucketName + "/" + fileName)
                                .build()
                );
            }

            // 设置响应头
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=download.zip");

            // 创建 ZIP 输出流
            try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
   
                for (String fileName : fileNames) {
   
                    String objectName = tempFolderName + "/" + fileName;

                    // 获取临时文件夹中的每个文件流
                    try (InputStream inputStream = minioClient.getObject(
                            GetObjectArgs.builder().bucket(bucketName).object(objectName).build())) {
   

                        // 写入 ZIP 条目
                        zipOut.putNextEntry(new ZipEntry(fileName));

                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = inputStream.read(buffer)) >= 0) {
   
                            zipOut.write(buffer, 0, length);
                        }
                        zipOut.closeEntry();  // 结束条目写入
                    }
                }
                zipOut.finish();  // 完成 ZIP 文件
            }

            // 下载完成后删除临时文件夹
            deleteFolder(tempFolderName);

        } catch (Exception e) {
   
            throw new RuntimeException("Error occurred while downloading folder as zip", e);
        }
    }

    // 删除指定文件夹及其内容
    private void deleteFolder(String folderName) {
   
        try {
   
            Iterable<Result<Item>> items = minioClient.listObjects(ListObjectsArgs.builder()
                    .bucket(bucketName)
                    .prefix(folderName + "/")
                    .recursive(true)
                    .build());

            for (Result<Item> itemResult : items) {
   
                Item item = itemResult.get();
                minioClient.removeObject(
                        RemoveObjectArgs.builder().bucket(bucketName).object(item.objectName()).build()
                );
            }
        } catch (Exception e) {
   
            throw new RuntimeException("Error occurred while deleting folder", e);
        }
    }
}
3. 创建控制器

控制器方法用于接受文件名列表并调用服务中的方法进行下载。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

@RestController
public class FileDownloadController {
   

    @Autowired
    private MinioService minioService;

    @GetMapping("/download-zip")
    public void downloadZip(@RequestParam List<String> fileNames, HttpServletResponse response) {
   
        minioService.downloadFolderAsZip(fileNames, response);
    }
}
4. 测试

可以通过以下 GET 请求测试功能:

GET http://localhost:8080/download-zip?fileNames=file1.txt&fileNames=file2.jpg&fileNames=file3.pdf
注意事项
  • 异步清理:如果文件数量多或者体积大,删除文件夹可能会影响性能。可以考虑将删除操作异步处理。
  • 异常处理:添加异常处理逻辑,确保在复制、压缩、删除等环节处理各种可能的错误。

3、在minio指定的桶名下面生产一个临时文件夹

SpringBoot+minio实现多文件下载时在minio指定的桶名下面生产一个文件夹,将需要下载放到这个文件夹中,并把这个文件夹打成一个压缩包后进行下载,下载成功后保留压缩包信息存放到数据库并且删除这个文件夹

要实现此功能,需要将多个文件上传到一个临时文件夹,并将该文件夹压缩为一个 ZIP 文件,供客户端下载。在下载成功后,将压缩包信息存储到数据库,并删除临时文件夹的所有文件。

以下是实现步骤和代码:

  1. 创建 MinIO 文件夹:在 MinIO 的指定桶下创建一个临时文件夹,并将文件复制到该文件夹中。
  2. 打包下载:将文件夹打包为 ZIP 文件返回给客户端。
  3. 保存记录:将 ZIP 文件信息存储到数据库中。
  4. 清理临时文件夹:下载完成后,删除临时文件夹中的所有文件,但保留 ZIP 文件。
1. 配置 MinIO 客户端

application.properties 中添加 MinIO 和数据库的配置:

# MinIO 配置
minio.url=http://localhost:9000
minio.accessKey=your-access-key
minio.secretKey=your-secret-key
minio.bucketName=your-bucket

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/yourdb
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
2. 创建数据库实体类

创建一个实体类 ZipFileRecord 来保存压缩包信息:

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
public class ZipFileRecord {
   
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String fileName;
    private String filePath;
    private LocalDateTime createdTime;

    // Getters and Setters
    // ...
}
3. 创建存储库接口

创建一个 ZipFileRecordRepository,用于保存压缩包信息:

import org.springframework.data.jpa.repository.JpaRepository;

public interface ZipFileRecordRepository extends JpaRepository<ZipFileRecord, Long> {
   
}
4. MinIO 服务实现

编写服务类 MinioService,完成文件夹创建、文件复制、打包下载、数据库保存和清理的逻辑。

import io.minio.*;
import io.minio.errors.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class MinioService {
   

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private ZipFileRecordRepository zipFileRecordRepository;

    @Value("${minio.bucketName}")
    private String bucketName;

    public void downloadFolderAsZip(List<String> fileNames, HttpServletResponse response) {
   
        String tempFolderName = "temp-folder-" + UUID.randomUUID();  // 创建临时文件夹
        String zipFileName = "download-" + UUID.randomUUID() + ".zip";
        String zipFilePath = tempFolderName + "/" + zipFileName;

        try {
   
            // 复制文件到临时文件夹
            for (String fileName : fileNames) {
   
                String objectName = tempFolderName + "/" + fileName;

                minioClient.copyObject(
                        CopyObjectArgs.builder()
                                .bucket(bucketName)
                                .object(objectName)
                                .source(bucketName + "/" + fileName)
                                .build()
                );
            }

            // 设置响应头,下载压缩包
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=" + zipFileName);

            // 创建 ZIP 输出流
            try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
   
                for (String fileName : fileNames) {
   
                    String objectName = tempFolderName + "/" + fileName;

                    // 获取每个文件的输入流
                    try (InputStream inputStream = minioClient.getObject(
                            GetObjectArgs.builder().bucket(bucketName).object(objectName).build())) {
   

                        // 写入 ZIP 条目
                        zipOut.putNextEntry(new ZipEntry(fileName));
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = inputStream.read(buffer)) >= 0) {
   
                            zipOut.write(buffer, 0, length);
                        }
                        zipOut.closeEntry();  // 结束条目写入
                    }
                }
                zipOut.finish();  // 完成 ZIP 文件
            }

            // 将 ZIP 文件信息保存到数据库
            saveZipFileRecord(zipFileName, zipFilePath);

            // 删除临时文件夹中的文件
            deleteFolder(tempFolderName);

        } catch (Exception e) {
   
            throw new RuntimeException("Error occurred while downloading folder as zip", e);
        }
    }

    // 保存 ZIP 文件信息到数据库
    private void saveZipFileRecord(String zipFileName, String zipFilePath) {
   
        ZipFileRecord record = new ZipFileRecord();
        record.setFileName(zipFileName);
        record.setFilePath(zipFilePath);
        record.setCreatedTime(LocalDateTime.now());
        zipFileRecordRepository.save(record);
    }

    // 删除指定文件夹及其内容
    private void deleteFolder(String folderName) {
   
        try {
   
            Iterable<Result<Item>> items = minioClient.listObjects(
                    ListObjectsArgs.
您可以使用MinioJava SDK来实现批量下载文件的功能。首先,您需要使用Minio的listObjects方法获取指定文件夹下的所有文件的objectName。您可以使用ListObjectsArgs.builder().recursive(true)来设置递归获取文件夹下的文件路径。然后,根据获取到的objectName逐个下载文件即可。 以下是一个示例代码片段,展示了如何使用MinioJava SDK来实现批量下载文件的功能: ```java import io.minio.MinioClient; import io.minio.Result; import io.minio.messages.Item; import io.minio.errors.MinioException; import java.util.ArrayList; import java.util.List; public class MinioDownloader { private MinioClient minioClient; public MinioDownloader() { // 初始化MinioClient minioClient = MinioClient.builder() .endpoint("your-minio-endpoint") .credentials("your-access-key", "your-secret-key") .build(); } public void downloadFilesInFolder(String folderPath, String destinationPath) { try { // 获取文件夹下的所有文件的objectName List<String> objectNameList = getAllObjectNameInFolder(folderPath); // 逐个下载文件 for (String objectName : objectNameList) { minioClient.downloadObject("your-bucket", objectName, destinationPath + "/" + objectName); } System.out.println("Files downloaded successfully."); } catch (Exception e) { e.printStackTrace(); } } public List<String> getAllObjectNameInFolder(String folderPath) { try { ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder() .bucket("your-bucket") .prefix(folderPath) .recursive(true) .build(); Iterable<Result<Item>> results = minioClient.listObjects(listObjectsArgs); List<String> objectNameList = new ArrayList<>(); for (Result<Item> item : results) { objectNameList.add(item.get().objectName()); } return objectNameList; } catch (Exception e) { e.printStackTrace(); return new ArrayList<>(); } } } ``` 请注意,您需要将代码中的"your-minio-endpoint"、"your-access-key"、"your-secret-key""your-bucket"替换为您自己的Minio配置信息。另外,您还需要指定下载文件的目标路径。 希望这可以帮助到您! #### 引用[.reference_title] - *1* [Minio 批量下载文件,并压缩文件,使用sftp上传文件](https://blog.csdn.net/Lifeime/article/details/124942052)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [minIO中打包下载文件夹](https://blog.csdn.net/qq_38431321/article/details/130496135)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北执南念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值