SpringBoot 结合 minio

时间:2024-11-27 14:46:24

下面是在 Spring Boot 项目中集成 MinIO,并提供上传、下载和生成免密下载链接的功能。

1. 添加依赖

首先,在 pom.xml 文件中添加 Spring Boot 和 MinIO 的相关依赖。

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MinIO Java SDK -->
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.3.5</version>
    </dependency>

    <!-- Lombok for getter/setter/toString/etc. -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

2. 配置 MinIO 连接

application.propertiesapplication.yml 文件中配置 MinIO 连接信息。

application.properties
minio.endpoint=http://localhost:9000
minio.access-key=minioadmin
minio.secret-key=minioadmin
minio.bucket-name=my-bucket
application.yml
minio:
  endpoint: http://localhost:9000
  access-key: minioadmin
  secret-key: minioadmin
  bucket-name: my-bucket

3. 创建 MinIO 配置类

创建一个配置类来初始化 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.endpoint}")
    private String endpoint;

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

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

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

4. 创建 MinIO 操作工具类

为了方便使用 MinIO,可以创建一个工具类来封装常用的操作。

import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.MinioException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.Date;

@Component
public class MinioUtil {

    @Autowired
    private MinioClient minioClient;

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

    // 初始化桶
    public void initBucket() throws MinioException {
        if (!minioClient.bucketExists(bucketName)) {
            minioClient.makeBucket(bucketName);
        }
    }

    // 上传文件
    public String uploadFile(String objectName, InputStream inputStream, String contentType) throws MinioException {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(inputStream, inputStream.available(), -1)
                        .contentType(contentType)
                        .build()
        );
        return getObjectUrl(objectName);
    }

    // 下载文件
    public InputStream downloadFile(String objectName) throws MinioException {
        return minioClient.getObject(
                io.minio.GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
    }

    // 生成免密下载链接
    public String generatePresignedUrl(String objectName, long expirationInSeconds) throws MinioException {
        return minioClient.getPresignedObjectUrl(
                io.minio.GetPresignedObjectUrlArgs.builder()
                        .method(io.minio.http.Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expirationInSeconds)
                        .build()
        );
    }

    // 获取对象的 URL
    public String getObjectUrl(String objectName) {
        return minioClient.getObjectUrl(bucketName, objectName);
    }
}

5. 创建 Controller 层

创建控制器层来处理 HTTP 请求,并使用 MinIO 工具类进行操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Date;

@RestController
@RequestMapping("/minio")
public class MinioController {

    @Autowired
    private MinioUtil minioUtil;

    // 初始化桶
    @GetMapping("/init-bucket")
    public String initBucket() {
        try {
            minioUtil.initBucket();
            return "Bucket initialized successfully";
        } catch (Exception e) {
            return "Failed to initialize bucket: " + e.getMessage();
        }
    }

    // 上传文件
    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            String objectName = file.getOriginalFilename();
            String url = minioUtil.uploadFile(objectName, inputStream, file.getContentType());
            return "File uploaded successfully: " + url;
        } catch (Exception e) {
            return "Failed to upload file: " + e.getMessage();
        }
    }

    // 下载文件
    @GetMapping("/download/{objectName}")
    public ResponseEntity<InputStream> downloadFile(@PathVariable String objectName) {
        try {
            InputStream inputStream = minioUtil.downloadFile(objectName);
            return ResponseEntity.ok()
                    .header("Content-Disposition", "attachment; filename=\"" + objectName + "\"")
                    .body(inputStream);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    // 生成免密下载链接
    @GetMapping("/presigned-url/{objectName}")
    public String generatePresignedUrl(@PathVariable String objectName, @RequestParam long expirationInSeconds) {
        try {
            String url = minioUtil.generatePresignedUrl(objectName, expirationInSeconds);
            return "Presigned URL: " + url;
        } catch (Exception e) {
            return "Failed to generate presigned URL: " + e.getMessage();
        }
    }
}

6. 启动类

确保启动类位于正确的包路径下,以便 Spring Boot 自动扫描到所有组件。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

7. 测试

启动应用并测试各个接口是否正常工作。

mvn spring-boot:run

可以使用 Postman 或其他 HTTP 客户端来测试这些接口。

快捷方式和最佳实践

  1. Lombok:使用 Lombok 可以大大减少样板代码,如 gettersettertoString 等。
  2. 全局异常处理:使用 @ControllerAdvice 注解创建全局异常处理器,统一处理异常。
  3. 日志记录:使用 logbacklog4j2 配置日志记录,方便调试和监控。
  4. 安全性:确保 MinIO 服务器的安全性,如设置访问密钥、限制访问 IP 等。
  5. 性能优化:合理设置 MinIO 的存储策略和网络配置,避免性能瓶颈。