.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




