使用预签名 URL 从 PUT 到 S3 的 400 错误请求

Ree*_*ard 8 javascript browser xmlhttprequest amazon-s3 aws-sdk

我正在尝试将视频文件从 JS 上传到 S3 存储桶,但现在收到 400 错误请求。我确信我已经正确设置了一切,但我可​​以做一些事情。

我在服务器上生成一个 URL,如下所示:

const client = new S3({
    accessKeyId: 'id-ommited',
    secretAccessKey: 'key-ommited',
    region: 'eu-west-2',
    useAccelerateEndpoint: true
});
const url = client.getSignedUrl('putObject', {
    Bucket:  'screen-capture-uploads',
    Key:     'video.webm',
    Expires: 60 * 60,
    ContentType: 'application/octet-stream'
});
Run Code Online (Sandbox Code Playgroud)

这个 URL 在我的前端似乎没问题,我将它传递给 XMLHttpRequest,如下所示

const xhr = new XMLHttpRequest();

xhr.open('PUT', body.url); // body.url being the presigned url
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send(blob); // blob being the webm binary
Run Code Online (Sandbox Code Playgroud)

我正在使用 CORS 设置,只允许从任何地方进行 PUT

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Run Code Online (Sandbox Code Playgroud)

我检查了一下,效果很好。IAM 用户也有权放入存储桶

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::screen-capture-uploads/*"
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我设法解决了我的问题。我看过其他一些答案,但没有发现任何对我有用的东西。有人对我有什么想法吗?

Ree*_*ard 4

我获取了它生成的端点,然后将其直接放入浏览器中。原来我没有在我使用的存储桶上启用传输加速!

这只是变成了一个错误的请求,没有任何额外的信息

  • S3 在响应正文中提供额外信息。`&lt;Error&gt;&lt;Code&gt;InvalidRequest&lt;/Code&gt;&lt;Message&gt;此存储桶上未配置 S3 传输加速&lt;/Message&gt;...`,但如果没有启用传输加速,您可能也不会获得任何 CORS 标头,所以大概预检检查失败,浏览器不会给你正文。 (2认同)