如何在MinIO预签名URL分片上传中设置文件大小限制?
针对你不想让应用接收文件、仅用预签名URL完成上传,同时要限制文件大小的需求,给你几个可行的落地方案:
1. 用MinIO桶策略直接限制单分片大小
MinIO支持通过桶策略的content-length-range条件,直接限制上传的分片大小,这是最直接的方式,不用修改应用代码,由MinIO直接拦截不符合大小的分片上传请求。
比如给目标桶添加这样的策略(针对分片上传的PutObject操作):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::your-bucket/*", "Condition": { "ContentLengthRange": [5242880, 104857600] // 限制分片大小在5MB到100MB之间(最后一片可更小,MinIO会自动兼容) } } ] }
用户用预签名URL上传分片时,若大小超出范围,MinIO会直接返回403错误,无需应用介入。
2. 初始化分片时提前校验总文件大小
修改你的StartMultiPartDto,让客户端传入文件总大小,在应用初始化分片时先判断是否超过允许的最大值,直接拦截不符合要求的请求:
首先更新Dto:
public class StartMultiPartDto { public string FileName { get; set; } public long TotalFileSize { get; set; } // 新增总大小字段 }
然后修改StartMultiPart接口:
[HttpPost("start-multipart")] public async Task<IActionResult> StartMultiPart([FromBody] StartMultiPartDto request) { // 假设允许的最大文件大小为10GB var maxAllowedSize = 10L * 1024 * 1024 * 1024; if (request.TotalFileSize > maxAllowedSize) { return BadRequest("文件大小超过限制"); } var key = Guid.NewGuid().ToString(); var uploadId = await _objectStorageService.StartMultiPart(key, request.FileName); return Ok(new { key, uploadId }); }
注意:客户端可能伪造总大小,需要后续步骤兜底校验。
3. 完成分片时校验实际总大小
在调用CompleteMultiPart时,先通过MinIO的API获取所有已上传分片的大小总和,对比限制值,不符合就终止上传:
修改CompleteMultiPart接口:
[HttpPost("{key}/complete-multipart")] public async Task<IActionResult> CompleteMultiPart([FromRoute] string key, [FromBody] CompleteMultiPartDto request) { var maxAllowedSize = 10L * 1024 * 1024 * 1024; // 获取所有已上传的分片信息 var parts = await _objectStorageService.ListParts(key, request.UploadId); var totalSize = parts.Sum(p => p.Size); if (totalSize > maxAllowedSize) { // 超过大小,终止分片上传 await _objectStorageService.AbortMultiPart(key, request.UploadId); return BadRequest("实际文件大小超过限制"); } await _objectStorageService.CompleteMultiPart(key, request.UploadId, request.Parts); return Ok(); }
对应的ObjectStorageService里需要实现ListParts方法,调用MinIO的ListPartsAsync接口即可。
4. 用MinIO事件通知做兜底校验
配置MinIO在对象上传完成后发送事件到你的应用,应用收到事件后检查对象大小,超过限制就删除该对象:
比如配置MinIO的事件通知,当s3:ObjectCreated:*事件触发时,发送到你的应用某个端点(该端点仅接收事件通知,不接收文件),然后在应用里处理:
[HttpPost("minio-event")] public async Task<IActionResult> HandleMinioEvent([FromBody] MinioEventNotification notification) { var maxAllowedSize = 10L * 1024 * 1024 * 1024; foreach (var record in notification.Records) { var objectSize = long.Parse(record.S3.Object.Size); if (objectSize > maxAllowedSize) { // 删除超出限制的对象 await _objectStorageService.DeleteObject(record.S3.Bucket.Name, record.S3.Object.Key); // 可记录日志或通知用户 } } return Ok(); }
这个方案作为最后一道防线,防止前面的校验被绕过。
你的现有代码可基于上面的方案调整,另外你的项目是video uploader,可根据视频上传场景调整大小限制的数值。
内容的提问来源于stack exchange,提问作者Luiz Kohler




