如何使用s3-request-presigner为PutObjectCommand预签名URL指定需签名的请求头
自定义请求头未被签名的解决方法
你在PutObjectCommand中传入的ACL、CacheControl、ContentType参数,SDK会自动映射为对应的x-amz-acl、Cache-Control、Content-Type请求头,默认会纳入签名范围,不需要额外手动配置signableHeaders。
你遇到的仅host被签名的问题,是因为手动指定signableHeaders时,头名大小写和SDK内部全小写的匹配规则不一致,导致你指定的头未被识别。
你可以直接省略signableHeaders配置即可正常签名所需头:
const command = new PutObjectCommand({ Bucket: 'mybucket', Key: 'file.txt', ACL: 'public-read', CacheControl: 'public, max-age=1000', ContentType: 'text/plain', }); const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 });
如果确实需要手动指定signableHeaders,请确保所有头名全小写,且必须包含host:
const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600, signableHeaders: new Set(['cache-control', 'content-type', 'x-amz-acl', 'host']) });
注意:使用生成的预签名URL发起PUT上传请求时,必须严格携带和签名时完全一致的Cache-Control、Content-Type、x-amz-acl请求头,否则会返回签名不匹配错误。
限制上传大小的实现方案
content-length-range参数仅适用于POST表单上传场景,PUT方式的预签名URL不支持原生限制上传大小,你可以选择以下两种方案:
- 业务层先校验上传文件大小,再调用预签名URL发起上传
- 改用POST预签名方式,在策略中配置
content-length-range规则,该规则会被纳入签名,超出大小的上传会被S3直接拒绝,示例代码如下:
import { createPresignedPost } from "@aws-sdk/s3-presigned-post"; const { url, fields } = await createPresignedPost(s3Client, { Bucket: 'mybucket', Key: 'file.txt', Expires: 3600, Conditions: [ ["content-length-range", 1024, 10 * 1024 * 1024], // 限制文件大小在1KB到10MB之间 ["eq", "$CacheControl", "public, max-age=1000"], ["eq", "$ContentType", "text/plain"], ["eq", "$x-amz-acl", "public-read"] ], Fields: { "Cache-Control": "public, max-age=1000", "Content-Type": "text/plain", "x-amz-acl": "public-read" } });
生成的fields包含所有需要和文件一起提交的表单字段,前端使用POST方式提交FormData到返回的url即可完成上传。
内容的提问来源于stack exchange,提问作者Andrey Kononenko
相关产品推荐
相关产品推荐

