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

上传图片至S3 Bucket后文件损坏,请求协助排查修复

解决S3上传图片后无法打开的问题

你的代码存在三个核心问题,导致上传到S3的图片文件损坏:


1. 错误的流处理导致文件内容重复/无效

你先将文件内容读入fileBytes数组并写入MemoryStream,随后又调用file.CopyTo(stream),这会把原文件内容再次追加到流中,最终上传到S3的文件是原文件的两倍大小,直接导致文件损坏。同时,MemoryStream写入fileBytes后,流的位置停在末尾,直接上传会让S3读取空内容。

2. 错误设置ContentEncoding请求头

你在PutObjectRequest中添加了ContentEncoding = "base64",但实际上并没有对图片文件进行base64编码操作。这会让S3和下载端错误地尝试对二进制图片数据进行base64解码,导致文件内容错乱。

3. 文件读取不完整的风险

同步调用file.OpenReadStream().Read()时,该方法返回实际读取的字节数,无法保证一次性读完整个文件,可能导致部分内容丢失。


修正后的上传代码(推荐方案)

直接使用文件的原始流,避免不必要的字节数组转换和流复制:

private async Task<string> UploadFile(IFormFile file, string prefix, CancellationToken cancellationToken)
{
    try
    {
        var fullPath = $"{prefix}/{file.FileName}";

        using (var stream = file.OpenReadStream())
        {
            var request = new PutObjectRequest
            {
                BucketName = _bucketName,
                Key = fullPath,
                InputStream = stream,
                Headers =
                {
                    ContentDisposition = "attachment;"
                },
                ContentType = file.ContentType
            };

            await _client.PutObjectAsync(request, cancellationToken);
        }

        return fullPath;
    }
    catch (Exception e)
    {
        Console.WriteLine("UploadAttachmentFileAsync-exception" + e.StackTrace);
        throw new Exception($"{e.Message}: {Constants.MSG_FILE_STORAGE_ACCESS_FAILED}");
    }
}

备选方案(保留字节数组处理)

如果必须使用字节数组中转,需修正流位置并移除重复复制操作:

private async Task<string> UploadFile(IFormFile file, string prefix, CancellationToken cancellationToken)
{
    try
    {
        byte[] fileBytes = new byte[file.Length];
        int bytesRead = await file.OpenReadStream().ReadAsync(fileBytes, 0, (int)file.Length);
        if (bytesRead != file.Length)
        {
            throw new IOException("未能完整读取文件内容");
        }

        var fullPath = $"{prefix}/{file.FileName}";

        using (var stream = new MemoryStream(fileBytes))
        {
            stream.Position = 0; // 重置流位置到开头

            var request = new PutObjectRequest
            {
                BucketName = _bucketName,
                Key = fullPath,
                InputStream = stream,
                Headers =
                {
                    ContentDisposition = "attachment;"
                },
                ContentType = file.ContentType
            };

            await _client.PutObjectAsync(request, cancellationToken);
        }

        return fullPath;
    }
    catch (Exception e)
    {
        Console.WriteLine("UploadAttachmentFileAsync-exception" + e.StackTrace);
        throw new Exception($"{e.Message}: {Constants.MSG_FILE_STORAGE_ACCESS_FAILED}");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 08:03:17