You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.Net Core中Minio PutObjectAsync上传大于12MB文件失败

解决Minio大文件上传签名不匹配问题

问题场景

当前使用以下代码向Minio存储桶保存文件:

public async Task SaveFileAsync(Stream stream, string fileName)
{
    MinioClient client = InitClient();

    bool found = await client.BucketExistsAsync(bucketName);
    if (!found)
    {
        await client.MakeBucketAsync(bucketName);
    }
    var fileType = "application/octet-stream";
    stream.Seek(0, SeekOrigin.Begin);
    await client.PutObjectAsync(bucketName, fileName, stream, stream.Length, fileType);
}

ASP.NET Core控制器中通过MemoryStream传递文件流:

public async Task<IActionResult> UploadAsync(int id, IFormFile file)
{
    var command = new MyApplicationCommand();
    using (var memoryStream = new MemoryStream())
    {
        await file.CopyToAsync(memoryStream);

        command.ContentStream = memoryStream;
        command.ContentType = file.ContentType;
        command.FileName = file.FileName;

        await mediator.Send(command); // 命令处理器调用SaveFileAsync
    }
}

上传大于12MB的文件时,PutObjectAsync返回错误:

MinIO API responded with message=The request signature we calculated does not match the signature you provided. Check your key and signing method.

堆栈跟踪信息:

at Minio.MinioClient.ParseError(IRestResponse response) in /home/maxim/dev/minio-dotnet/Minio/MinioClient.cs:line 491
   at Minio.MinioClient.<>c.<.ctor>b__81_0(IRestResponse response) in /home/maxim/dev/minio-dotnet/Minio/MinioClient.cs:line 75
   at Minio.MinioClient.HandleIfErrorResponse(IRestResponse response, IEnumerable`1 handlers, DateTime startTime) in /home/maxim/dev/minio-dotnet/Minio/MinioClient.cs:line 525
   at Minio.MinioClient.ExecuteTaskAsync(IEnumerable`1 errorHandlers, IRestRequest request, CancellationToken cancellationToken) in /home/maxim/dev/minio-dotnet/Minio/MinioClient.cs:line 371
   at Minio.MinioClient.PutObjectAsync(String bucketName, String objectName, String uploadId, Int32 partNumber, Byte[] data, Dictionary`2 metaData, Dictionary`2 sseHeaders, CancellationToken cancellationToken) in /home/maxim/dev/minio-dotnet/Minio/ApiEndpoints/ObjectOperations.cs:line 497
   at Minio.MinioClient.PutObjectAsync(String bucketName, String objectName, Stream data, Int64 size, String contentType, Dictionary`2 metaData, ServerSideEncryption sse, CancellationToken cancellationToken) in /home/maxim/dev/minio-dotnet/Minio/ApiEndpoints/ObjectOperations.cs:line 301

核心原因

Minio对大于默认分片阈值(通常10MB)的文件会自动启用分片上传。此时如果流的状态异常(如被提前释放、长度与实际读取内容不符),会导致每片请求的签名计算与服务器端不一致,触发错误。

解决步骤

1. 避免提前释放MemoryStream

控制器中的using块会在mediator.Send完成后立即释放MemoryStream,但分片上传是异步进行的,后续分片请求读取流时会失败,导致签名错误。修改控制器代码,确保流在上传完成后再释放:

public async Task<IActionResult> UploadAsync(int id, IFormFile file)
{
    var command = new MyApplicationCommand();
    var memoryStream = new MemoryStream();
    await file.CopyToAsync(memoryStream);

    command.ContentStream = memoryStream;
    command.ContentType = file.ContentType;
    command.FileName = file.FileName;

    try
    {
        await mediator.Send(command);
    }
    finally
    {
        memoryStream.Dispose(); // 上传完成后再释放流
    }

    return Ok();
}

2. 直接使用IFormFile的原始流(推荐)

没必要将文件复制到MemoryStream,直接使用IFormFile.OpenReadStream()可以减少内存占用,同时避免流状态问题:

public async Task<IActionResult> UploadAsync(int id, IFormFile file)
{
    var command = new MyApplicationCommand();
    command.ContentStream = file.OpenReadStream();
    command.ContentType = file.ContentType;
    command.FileName = file.FileName;

    await mediator.Send(command);

    return Ok();
}

同时修改SaveFileAsync,使用传入的ContentType而非硬编码:

public async Task SaveFileAsync(Stream stream, string fileName, string contentType)
{
    MinioClient client = InitClient();

    bool found = await client.BucketExistsAsync(bucketName);
    if (!found)
    {
        await client.MakeBucketAsync(bucketName);
    }
    stream.Seek(0, SeekOrigin.Begin);
    await client.PutObjectAsync(bucketName, fileName, stream, stream.Length, contentType);
}

3. 验证Minio客户端版本

旧版本的Minio .NET SDK可能存在分片上传的签名计算bug,升级到最新稳定版(通过NuGet更新Minio包)。

4. 检查客户端配置

确保InitClient()中配置的:

  • 访问密钥(Access Key)和秘密密钥(Secret Key)正确
  • Minio服务器端点(Endpoint)正确,包含协议(http/https)和端口
  • 区域(Region)与Minio服务器配置一致(如果服务器设置了区域)

内容的提问来源于stack exchange,提问作者dawid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:07:01