springboot+minio分片上传大文件
时间: 2025-03-26 09:25:26 浏览: 49
### 使用 Spring Boot 和 MinIO 实现大文件分片上传
#### 设计思路
为了高效处理大文件的分片上传,系统设计应考虑以下几个方面:
- **异步多线程**:通过 `MinioSysFileServiceImpl` 类采用异步方式执行文件上传操作,在前端调用时立即返回文件路径而不等待实际上传过程结束[^1]。
- **状态监控**:利用 MinIO API 定期检查文件是否存在以确认上传是否成功完成[^1]。
- **秒传功能**:引入 MD5 编码机制配合 Redis 存储已存在文件哈希值,从而支持秒传特性。
#### 技术选型与依赖管理
项目基于 Spring Boot 构建,并集成 MinIO SDK 来简化对象存储交互逻辑。具体技术栈如下:
- Java 8+
- Maven 或 Gradle (构建工具)
- Spring Boot Web, AOP 模块
- MinIO Client Library for Java (`minio`)
- Redis (用于缓存)
对于版本控制,建议使用稳定的 MinIO 库版本并保持与其他组件兼容性良好。例如,可参照提供的 Gitee 上开源项目的配置[^2]。
#### 关键代码片段展示
##### 初始化 MinIO 配置类
```java
import io.minio.MinioClient;
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Bean
public MinioClient minioClient() throws Exception{
return MinioClient.builder()
.endpoint(endpoint)
.credentials("ACCESS_KEY", "SECRET_KEY") // 替换成自己的密钥
.build();
}
}
```
##### 文件服务接口定义
```java
@Service
@Slf4j
public class FileService {
@Autowired
private MinioClient minioClient;
/**
* 创建桶(如果不存在)
*/
public void createBucket(String bucketName){
try {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!found) {
log.info("创建新的桶 {}", bucketName);
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}else{
log.warn("{} 已经存在.", bucketName);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e.getCause());
}
}
/**
* 分片上传方法
*/
public CompletableFuture<String> uploadPart(FileInputStream fileStream, long partSize, int partNumber,
String objectName, String uploadId, Map<Integer, PartETag> etagsMap) {
return CompletableFuture.supplyAsync(() -> {
try {
UploadPartResponse response = minioClient.uploadPart(
UploadPartArgs.builder()
.bucket("your-bucket-name")
.object(objectName)
.uploadId(uploadId)
.partNumber(partNumber)
.stream(fileStream, partSize, -1L)
.build());
etagsMap.put(partNumber, response.etag()); // 记录 ETag
return "Part uploaded successfully";
} catch (Exception ex) {
throw new CompletionException(ex);
}
});
}
}
```
##### 控制器层实现
```java
@RestController
@RequestMapping("/api/file")
public class FileController {
@Autowired
private FileService fileService;
@PostMapping("/multipart/upload/{fileName}")
public ResponseEntity<?> startMultipartUpload(@PathVariable String fileName) {
// 启动 Multipart Upload 流程...
return ResponseEntity.ok(/* 返回初始化信息 */);
}
@PutMapping("/multipart/part/{uploadId}/{partNumber}")
public ResponseEntity<?> uploadPart(@RequestParam("file") MultipartFile multipartFile,
@PathVariable String uploadId,
@PathVariable Integer partNumber) {
try(InputStream inputStream = multipartFile.getInputStream()){
// 执行具体的分片上传业务逻辑...
return ResponseEntity.status(HttpStatus.CREATED).body(null);
}catch(Exception e){
return ResponseEntity.badRequest().body(e.getMessage());
}
}
@PostMapping("/multipart/complete/{uploadId}")
public ResponseEntity<?> completeMultipartUpload(@PathVariable String uploadId,
List<PartETag> partsEtags) {
// 结束 Multipart Upload 并提交所有部分...
return ResponseEntity.noContent().build();
}
}
```
阅读全文
相关推荐


















