You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

.NET AWS Lambda写入S3文件报错:无法确定内容长度

解决AWS Lambda中PutObjectRequest上传S3流时的「Could not determine content length」错误

嘿,这个问题我之前踩过坑!错误的核心原因是你直接用了从S3获取的ResponseStream作为上传输入流——这个流属于不可查找的网络流,没法直接获取内容长度,而AWS SDK在处理PutObject请求时必须知道流的长度才能完成上传操作。

快速解决:把流复制到MemoryStream再上传

你需要先把ResponseStream的内容完整复制到MemoryStream中,因为MemoryStream支持位置重置和长度获取,刚好能满足SDK的要求。修改后的关键代码如下:

using(var objectResponse = await this.S3Client.GetObjectAsync(s3Event.Bucket.Name, s3Event.Object.Key))
{
    using(Stream responseStream = objectResponse.ResponseStream)
    {
        // 先将网络流复制到内存流
        using(var memoryStream = new MemoryStream())
        {
            await responseStream.CopyToAsync(memoryStream);
            // 重置内存流的位置到开头,否则上传会从流的末尾开始,传空内容
            memoryStream.Position = 0;
            
            await this.S3Client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
            {
                BucketName = s3Event.Bucket.Name,
                Key = fileNameWithoutExtension + ".thumb" + extension,
                InputStream = memoryStream
            });
        }
    }
}

为什么这样能解决问题?

  • S3返回的ResponseStream是流式传输的网络流,它不会把整个文件预加载到内存里,所以无法直接读取Length属性,也不支持Seek操作;
  • MemoryStream会把流的内容全部加载到内存中,支持位置重置和长度查询,完全符合AWS SDK对上传流的要求。

额外小提示

如果你的处理对象是超大文件(比如几十上百MB),用MemoryStream可能会导致Lambda内存占用过高,这时候可以考虑用S3的分块上传(Multipart Upload)方案。不过从你的代码场景来看是生成缩略图,一般文件不会太大,用MemoryStream完全够用。

内容的提问来源于stack exchange,提问作者Wai Yan Hein

火山引擎 最新活动