哇,AWS 关于这些标头的文档太糟糕了。这是我想出来的。
-
createPresignedPost() 的输出是一个有两个键的对象:url 和fields。 fields 对象包含提交帖子时必须使用的所有表单字段和相应的值。您可以将这些字段并且仅将这些字段复制到您的 Postman 请求中。
- AWS SDK 会自动添加一些字段,包括
bucket、key、policy,以及生成签名所需的几个字段。对于 JavaScript SDK,它们是 X-Amz-Algorithm、X-Amz-Credential、X-Amz-Date 和 X-Amz-Signature(尽管对于 Python SDK,它们是 AWSAccessKeyId 和 signature)。这些将在createPresignedPost() 的fields 键中返回,因此您无需手动生成它们。
-
createPresignedPost() 的Fields 参数用于您要添加到表单的其他字段。 here 列出了可能添加的整个字段集。但是,SDK 会为您处理其中的许多,尤其是必需的。根据Python SDK docs,您可以在Fields 中包含的字段为acl、Cache-Control、Content-Type、Content-Disposition、Content-Encoding、Expires、success_action_redirect、@9876544 success_action_status 和 x-amz-meta-。
-
createPresignedPost() 的Fields 和Conditions 参数需要同步,以便Fields 中的任何字段在Conditions 中也有条件,反之亦然。
总而言之,我认为您的getSignedUrl() 函数的问题在于它缺少createPresignedPost() 的Fields 参数,该参数具有Content-Type 的键值对(因为您有@ 987654360@)。如果Fields 参数中没有Content-Type,计算的签名将不包括Content-Type 字段。如果您随后遗漏了Content-Type 字段,您的签名可能匹配,但您的策略条件将失败,因为它要求Content-Type 存在并且等于image/jpeg。如果您包含Content-Type,那么您的签名将不匹配。
这可能对你有用。
const { createPresignedPost } = require("@aws-sdk/s3-presigned-post");
const { S3Client } = require("@aws-sdk/client-s3");
const s3 = new S3Client({
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
signatureVersion: "v4",
region: "eu-west-2",
});
async function getSignedUrl() {
const params = {
Bucket: "richbits-test",
Key: "d3c0c9a0-ff91-11eb-bbe6-b9d90cd8bb8f",
Conditions: [["eq", "$Content-Type", "image/jpeg"]],
Fields: {"Content-Type": "image/jpeg"},
};
console.log(params);
const signedUrl = await createPresignedPost(s3, params);
return signedUrl;
}
getSignedUrl().then(res => {
console.log(res)
})
这个的输出应该是
{
Bucket: 'richbits-test',
Key: 'd3c0c9a0-ff91-11eb-bbe6-b9d90cd8bb8f',
Conditions: [ [ 'eq', '$Content-Type', 'image/jpeg' ] ],
Fields: { 'Content-Type': 'image/jpeg' }
}
{
url: 'https://s3.eu-west-2.amazonaws.com/richbits-test',
fields: {
'Content-Type': 'image/jpeg',
bucket: 'richbits-test',
'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
'X-Amz-Credential': '<YOUR_ACCESS_KEY_ID>/20211005/eu-west-2/s3/aws4_request',
'X-Amz-Date': '20211005T111446Z',
key: 'd3c0c9a0-ff91-11eb-bbe6-b9d90cd8bb8f',
Policy: '<SOME_BASE64_ENCODED_STRING>',
'X-Amz-Signature': '<THE_SIGNATURE>'
}
}
那么您的 POST 请求将包括表单字段 Content-Type、bucket、X-Amz-Algorithm、X-Amz-Credential、X-Amz-Date、Policy 和 X-Amz-Signature。这是 HTML 表单的外观。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="https://s3.eu-west-2.amazonaws.com/richbits-test" method="post" enctype="multipart/form-data">
Bucket:
<input type="input" name="bucket" value="richbits-test" /><br />
Key to upload:
<input type="input" name="key" value="d3c0c9a0-ff91-11eb-bbe6-b9d90cd8bb8f" /><br />
Content-Type:
<input type="input" name="Content-Type" value="image/jpeg" /><br />
<input type="text" name="X-Amz-Credential" value="<YOUR_ACCESS_KEY_ID>/20211005/eu-west-2/s3/aws4_request" />
<input type="text" name="X-Amz-Date" value="20211005T111446Z" />
<input type="hidden" name="Policy" value="<SOME_BASE64_ENCODED_STRING>" />'
<input type="hidden" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="hidden" name="X-Amz-Signature" value="<THE_SIGNATURE>" />
File:
<input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
</html>
就调试这个问题而言,我没有从POST 对 S3 的请求中找到任何有用的信息。我要么没有得到回应,要么处于未经授权的状态,没有任何迹象表明问题出在哪里。