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可以为应用提供更加稳定、高效的文件上传解决方案,使用户体验显著提升。