JAVA:Minio 实现文件切片快速上传的技术指南

请关注微信公众号:拾荒的小海螺

博客地址:http://lsk-ww.cn/

1、简述

在现代 Web 应用中,大文件上传是一个常见的需求。传统的文件上传方式在面对大文件时往往效率低下,并且容易出现超时或失败的问题。通过文件切片上传技术,我们可以将大文件分割成多个小块并行上传,大大提高上传速度和稳定性。本文将介绍如何使用 Spring Boot 和 Minio 实现文件切片极速上传。

2、环境准备

  • Spring Boot 项目配置
    创建一个新的 Spring Boot 项目,并在 pom.xml 中添加必要的依赖:
bash 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.3.0</version>
    </dependency>
</dependencies>

3、实现文件切片上传

3.1 配置 Minio 客户端

在 Spring Boot 项目中,配置 Minio 客户端:

bash 复制代码
import io.minio.MinioClient;
import io.minio.errors.MinioException;
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.accessKey}")
    private String accessKey;

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

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

在 application.properties 文件中添加 Minio 配置信息:

bash 复制代码
minio.endpoint=http://localhost:9000
minio.accessKey=YOUR_ACCESS_KEY
minio.secretKey=YOUR_SECRET_KEY
3.2 文件切片上传接口

创建一个控制器来处理文件切片上传请求:

bash 复制代码
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.MinioException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

@RestController
@RequestMapping("/upload")
public class UploadController {

    @Autowired
    private MinioClient minioClient;

    @PostMapping("/chunk")
    public String uploadChunk(@RequestParam("file") MultipartFile file,
                              @RequestParam("chunkIndex") int chunkIndex,
                              @RequestParam("chunkTotal") int chunkTotal,
                              @RequestParam("identifier") String identifier) {
        try {
            String bucketName = "mybucket";
            String objectName = identifier + "/" + chunkIndex;
            InputStream inputStream = file.getInputStream();
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                            inputStream, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());
            return "Chunk " + chunkIndex + " uploaded successfully.";
        } catch (MinioException | IOException e) {
            e.printStackTrace();
            return "Error: " + e.getMessage();
        }
    }
}
3.3 合并文件切片

当所有文件切片上传完成后,需要合并这些切片形成完整文件:

bash 复制代码
import io.minio.ComposeObjectArgs;
import io.minio.ComposeSource;
import io.minio.errors.MinioException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;

@PostMapping("/merge")
public String mergeChunks(@RequestParam("identifier") String identifier,
                          @RequestParam("chunkTotal") int chunkTotal) {
    try {
        String bucketName = "mybucket";
        List<ComposeSource> sources = new ArrayList<>();
        for (int i = 0; i < chunkTotal; i++) {
            sources.add(ComposeSource.builder()
                    .bucket(bucketName)
                    .object(identifier + "/" + i)
                    .build());
        }

        minioClient.composeObject(
                ComposeObjectArgs.builder()
                        .bucket(bucketName)
                        .object(identifier)
                        .sources(sources)
                        .build());

        return "File merged successfully.";
    } catch (MinioException e) {
        e.printStackTrace();
        return "Error: " + e.getMessage();
    }
}

4、前端实现文件切片上传

前端需要将大文件切割成小块并逐块上传到服务器。以 JavaScript 为例:

bash 复制代码
async function uploadFile(file) {
    const chunkSize = 5 * 1024 * 1024; // 5MB
    const totalChunks = Math.ceil(file.size / chunkSize);

    for (let i = 0; i < totalChunks; i++) {
        const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
        const formData = new FormData();
        formData.append('file', chunk);
        formData.append('chunkIndex', i);
        formData.append('chunkTotal', totalChunks);
        formData.append('identifier', file.name);

        await fetch('/upload/chunk', {
            method: 'POST',
            body: formData,
        });
    }

    // 合并切片
    await fetch('/upload/merge', {
        method: 'POST',
        body: JSON.stringify({
            identifier: file.name,
            chunkTotal: totalChunks
        }),
        headers: {
            'Content-Type': 'application/json'
        }
    });
}

5、总结

通过 Spring Boot 和 Minio 的结合,我们可以轻松实现文件切片上传功能。该技术不仅提升了大文件上传的效率,还提高了上传的可靠性和用户体验。希望本文能帮助你在项目中实现这一功能。

完整的示例代码和详细配置可以根据实际需求进行调整和优化。祝你在项目开发中取得成功!

相关推荐
专注仿真3 分钟前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
霸道流氓气质22 分钟前
智能客服组件:分层意图识别、RAG Advisor 与人工转接状态机的 Vue3 + Spring AI 生产级实战
java·人工智能·spring
jimy143 分钟前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
captain3761 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
呆呆虫121 小时前
用 orjson 加速 SerpBase 响应解析:基准对比与注意事项
开发语言·php
心中有你02141 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
心疼你的一切2 小时前
Python自动发邮件实战定时发报表
大数据·开发语言·python
步行cgn2 小时前
Spring MVC + Thymeleaf 模板解析失败:从 500 错误到页面正常显示
java·spring·mvc
lgcgkCQ2 小时前
【AI 转型实战 1】SpringAI 入门:搭建基础大模型对话能力
java·ai·agent·rag·spring ai·mcp·langchain4j
Wang's Blog2 小时前
Java 项目实战:交友项目 - 用户体系集成总结
java·开发语言·交友