Lambda生成S3预签名URL供客户端PUT上传连接重置问题排查
方案可行性结论
在Lambda函数中生成S3预签名URL返回给客户端,由客户端直接发起无额外认证的HTTP PUT请求完成上传的方案完全可行。预签名URL本身的设计目标就是支持跨实体授权访问,生成URL的服务端和使用URL的客户端为不同实体不会导致连接异常。
报错核心原因
你遇到的连接被强制重置(WinError 10054)问题,核心原因是代码中分片编号不符合S3分片上传的规则:
- S3分片上传的
PartNumber参数取值范围是1到10000,为1起始计数,你当前服务端代码用for part in range(num_parts)生成的分片编号从0开始,传入非法的PartNumber=0时,S3会直接断开连接,不会返回标准错误响应。
必须补全的配置与代码修正点
- 修正分片编号逻辑:服务端生成预签名URL时,分片编号从1开始计数,同时显式设置匹配Lambda临时凭证有效期的过期时间,修正后的服务端代码片段如下:
presigned_upload_parts = [] # 分片编号从1开始,到num_parts结束 for part in range(1, num_parts + 1): resp = s3.generate_presigned_url( ClientMethod = 'upload_part', Params = { 'Bucket': os.environ['USER_UPLOADS_BUCKET'], 'Key': asset_id, 'UploadId': s3_upload_id, 'PartNumber': part }, # Lambda使用STS临时凭证,默认有效期1小时,预签名URL有效期不能超过该值 ExpiresIn=3600 ) presigned_upload_parts.append({"part": part, "url": resp}) return custom_http_response_wrapper(presigned_upload_parts)
- 校验Lambda执行角色权限:确保Lambda绑定的执行角色拥有目标S3桶的以下权限:
s3:PutObject、s3:CreateMultipartUpload、s3:UploadPart、s3:AbortMultipartUpload、s3:CompleteMultipartUpload。如果桶配置了自定义KMS密钥加密,还需要角色拥有对应KMS密钥的生成数据密钥、加密权限。 - 客户端请求注意事项:上传分片时不要额外添加
Authorization等签名类请求头,避免破坏预签名URL的签名匹配规则;除最后一个分片外,单个分片大小不能小于5MB,否则后续合并分片时会报错。 - 配置S3桶CORS规则:如果客户端是浏览器端,需要在S3桶配置跨域规则,允许客户端来源的PUT请求,同时暴露
ETag响应头,方便客户端获取分片上传返回的ETag用于后续合并操作。
额外排查点
如果修正上述问题后仍有异常,可逐一核对:
- 预签名URL未被URL编码篡改:确认返回给客户端的URL中特殊字符(比如签名里的
+、=,安全token里的斜杠等)没有被二次转义,URL参数完整无缺失。 - 网络访问无拦截:确认客户端到S3端点的网络没有被防火墙、代理拦截,没有配置错误的HTTPS证书校验规则。
内容的提问来源于stack exchange,提问作者Nevo
相关产品推荐
相关产品推荐

