Spring Boot+MinIO实战:掌握分片上传、秒传与断点续传,让文件管理更高效!

在现代应用中,随着文件大小的不断增大和网络环境的复杂化,传统的文件上传方式已难以满足用户需求。通过将Spring Boot与MinIO集成,可以轻松实现文件的分片上传、秒传和续传功能,为用户提供更流畅的上传体验。

图片

分片上传

分片上传是将大文件拆分成多个小块分别上传,避免单次上传大文件带来的不稳定性。使用MinIO的分片上传功能,可以在Spring Boot应用中轻松实现这一过程。通过MinIO的SDK,开发者可以将文件拆分为固定大小的块,并逐块上传到MinIO。所有块上传完成后,MinIO会自动合并这些块生成完整文件。

import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.UploadObjectArgs;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;

@RestController
public class ChunkUploadController {

    private final MinioClient minioClient;

    public ChunkUploadController(MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    @PostMapping("/upload/chunk")
    public String uploadChunk(@RequestParam("file") File file,
                              @RequestParam("chunkIndex") int chunkIndex,
                              @RequestParam("totalChunks") int totalChunks) throws Exception {

        String bucketName = "your-bucket-name";
        String objectName = "uploads/" + file.getName() + "_chunk_" + chunkIndex;

        // 上传分片
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .filename(file.getAbsolutePath())
                .build());

        return "Chunk " + chunkIndex + " uploaded successfully!";
    }

    // 在所有分片上传完毕后,你可以调用 MinIO 的合并接口来组合这些分片。
}

图片

秒传

秒传(Instant Upload)是通过计算文件的哈希值(如MD5),来检查服务器上是否已有相同文件,避免重复上传。如果文件已经存在,用户只需获取文件的访问链接,而无需重新上传整个文件,从而大大加快上传速度。

import io.minio.StatObjectArgs;
import io.minio.errors.MinioException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

@RestController
public class InstantUploadController {

    private final MinioClient minioClient;

    public InstantUploadController(MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    @GetMapping("/upload/instant")
    public String instantUpload(@RequestParam("fileName") String fileName,
                                @RequestParam("fileHash") String fileHash) throws Exception {

        String bucketName = "your-bucket-name";
        String objectName = "uploads/" + fileName;

        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return "File already exists. Skipping upload.";
        } catch (MinioException e) {
            // 文件不存在,继续上传流程
            return "File not found. Proceed with upload.";
        }
    }

    // 计算文件的 MD5 哈希值
    private String calculateFileHash(byte[] fileBytes) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(fileBytes);
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

图片

续传

续传功能允许用户在上传中断后,从断点继续上传,避免重复上传已成功部分。MinIO与Spring Boot的结合可以实现这一功能。通过记录上传进度,开发者可以让应用在网络中断或用户操作中断后,从上次中断的地方继续上传剩余部分。

import io.minio.GetObjectArgs;
import io.minio.PutObjectArgs;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

@RestController
public class ResumeUploadController {

    private final MinioClient minioClient;

    public ResumeUploadController(MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    @PostMapping("/upload/resume")
    public String resumeUpload(@RequestParam("file") File file,
                               @RequestParam("chunkIndex") int chunkIndex,
                               @RequestParam("totalChunks") int totalChunks) throws Exception {

        String bucketName = "your-bucket-name";
        String objectName = "uploads/" + file.getName() + "_chunk_" + chunkIndex;

        // 检查是否已经上传部分
        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return "Chunk " + chunkIndex + " already uploaded.";
        } catch (Exception e) {
            // 未上传,进行上传
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .filename(file.getAbsolutePath())
                    .build());
        }

        return "Chunk " + chunkIndex + " uploaded successfully!";
    }
}

通过将这些技术结合,Spring Boot和MinIO可以为应用提供更加稳定、高效的文件上传解决方案,使用户体验显著提升。

posted on 2024-09-23 10:18  IT-QI  阅读(83)  评论(0编辑  收藏  举报