最近开发功能需要大文件上传,正常会在业务代码中封装一层minio的上传,为了避免中转,实现了minio直传的方式。实现过程中也确实碰到了不少坑,只能查询文档,本着开箱即用,简单方便的原则,java版本的Minio sdk默认是不允许单独调用分片的相关方法,但是升级到8.0.3后可以通过继承MinioClient实现分片方法的使用,后来又碰到官方Minio版本的bug,提交issue,还好Minio github开发者处理非常迅捷,再次感谢,2021-02-04修复的,使用的开发者需要注意下。 大致描述下流程:
用户调用初始化接口,后端调用minio初始化,得到uploadId,生成每个分片的minio上传url
用户调用对应分片的上传地址,多次上传会覆盖
调用完成接口,后端查询所有上传的分片并合并
自定义minioClient
1 public class CustomMinioClient extends MinioClient { 2 3 protected CustomMinioClient(MinioClient client) { 4 super(client); 5 } 6 7 public String initMultiPartUpload(String bucket, String region, String object, Multimap<String, String> headers, Multimap<String, String> extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException { 8 CreateMultipartUploadResponse response = this.createMultipartUpload(bucket, region, object, headers, extraQueryParams); 9 10 return response.result().uploadId(); 11 } 12 13 public ObjectWriteResponse mergeMultipartUpload(String bucketName, String region, String objectName, String uploadId, Part[] parts, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException { 14 15 return this.completeMultipartUpload(bucketName, region, objectName, uploadId, parts, extraHeaders, extraQueryParams); 16 } 17 18 public ListPartsResponse listMultipart(String bucketName, String region, String objectName, Integer maxParts, Integer partNumberMarker, String uploadId, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException { 19 return this.listParts(bucketName, region, objectName, maxParts, partNumberMarker, uploadId, extraHeaders, extraQueryParams); 20 } 21 }
后端处理类
1 public Map<String, Object> initMultiPartUpload(String bucketName, String objectName, int totalPart) { 2 Map<String, Object> result = new HashMap<>(); 3 try { 4 String uploadId = customMinioClient.initMultiPartUpload(bucketName, null, objectName, null, null); 5 6 result.put("uploadId", uploadId); 7 List<String> partList = new ArrayList<>(); 8 9 Map<String, String> reqParams = new HashMap<>(); 10 //reqParams.put("response-content-type", "application/json"); 11 reqParams.put("uploadId", uploadId); 12 for (int i = 1; i <= totalPart; i++) { 13 reqParams.put("partNumber", String.valueOf(i)); 14 String uploadUrl = minioClient.getPresignedObjectUrl( 15 GetPresignedObjectUrlArgs.builder() 16 .method(Method.PUT) 17 .bucket(bucketName) 18 .object(objectName) 19 .expiry(1, TimeUnit.DAYS) 20 .extraQueryParams(reqParams) 21 .build()); 22 partList.add(uploadUrl); 23 } 24 result.put("uploadUrls", partList); 25 } catch (Exception e) { 26 logger.error("error: {}", e.getMessage(), e); 27 return null; 28 } 29 30 return result; 31 } 32 33 public boolean mergeMultipartUpload(String bucketName, String objectName, String uploadId) { 34 try { 35 Part[] parts = new Part[1000]; 36 //此方法注意2020.02.04之前的minio服务端有bug 37 ListPartsResponse partResult = customMinioClient.listMultipart(bucketName, null, objectName, 1000, 0, uploadId, null, null); 38 int partNumber = 1; 39 for (Part part : partResult.result().partList()) { 40 parts[partNumber - 1] = new Part(partNumber, part.etag()); 41 partNumber++; 42 } 43 customMinioClient.mergeMultipartUpload(bucketName, null, objectName, uploadId, parts, null, null); 44 } catch (Exception e) { 45 logger.error("error: {}", e.getMessage(), e); 46 return false; 47 } 48 49 return true; 50 }
注意:此处做了很多简单的操作还需自行优化,比如:
设定了最大仅允许1000个分片
初始化生成上传签名地址header头相关操作
等
整个流程看起来很简单,开始做的时候查询资料网上没有这么操作的,再加上又碰到了官方小bug(bug:listParts),还好社区活跃,不然只能老实的在业务中自己实现分片了。
完整的Demo地址:minio-multipart-upload,仅为实现流程,实现比较糙,需要进行优化改造。
参考文档:
AWS-CreateMultipartUpload
阿里-分片上传
————————————————
版权声明:本文为CSDN博主「tuine」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Tuine/article/details/113996848
浙公网安备 33010602011771号