400 错误请求通过签名请求上传到 Amazon S3

问题描述 投票:0回答:1

我正在用Django和React开发一个Web应用程序,部署在Heroku上,需要文件存储。根据 Heroku 的推荐,我使用的是 Amazon S3。但是,我似乎无法从前端将文件上传到我的 S3 存储桶。根据以下说明:https://devcenter.heroku.com/articles/s3-upload-python,我首先向后端请求签名的请求。 (我可以使用 boto3 在 Python 中很好地设置它,没有任何问题)。然后我使用签名信息尝试将实际文件上传到 S3。但这样做时,我不断收到 400 Bad Request 错误。

同样奇怪的是,我必须启用公共访问才能收到 400 错误,因为我曾经遇到过 403 Forbidden 错误,即使使用签名的凭据也是如此。

这是我的代码:

const config = { headers: { 'Content-Type': 'application/json' } }
const file_name = file.name
const file_type = file.type
const body = JSON.stringify({ file_name, file_type });
axios.post('/api/triggers/create/video/sign_request', body, config)
.then(res => {
  let content = {}
  for (var key in res.data.data.fields) {
    content[key] = res.data.data.fields[key]
  }
  content['file'] = file
  const config = { headers: { 'Content-Type': file.type } }
  axios.put(res.data.data.url, content, config)
  //...
})

我更喜欢使用 axios,但我也尝试了下面的代码,该代码在上面的 Heroku 教程中使用过。不幸的是,这会产生相同的结果。

const file_name = file.name
const file_type = file.type
const body = JSON.stringify({ file_name, file_type });
axios.post('/api/triggers/create/video/sign_request', body, config)
.then(res => {
  var fd = new FormData()
  for (var key in res.data.data.fields) {
    fd.append(key, res.data.data.fields[key])
  }
  fd.append('file', file)
  var xhr = new XMLHttpRequest();
  xhr.open('POST', res.data.data.url, true);
  xhr.send(fd)
  //...
})

用于签署请求的凭证与具有 S3 完全访问权限的 IAM 用户相关联。

我从 Django 后端返回的签名请求如下所示:

{
    "data": {
        "url": "https://my-bucket.s3.amazonaws.com/",
        "fields": {
            "acl": "public-read",
            "Content-Type": "video/mp4",
            "key": "funnycatisfunny.mp4",
            "AWSAccessKeyId": "BLABLABLAACCESSKEYBLABLABLA",
            "policy": "eyJleHBpcmF0aW9uIjogIjIwMjAtMDQtMDJUMTU6NDg6MTlaIiwgEtceteraEtCeterA",
            "signature": "S1GnAtuREWdleI4WXv5WHEBjc="
        }
    },
    "url": "https://my-bucket.s3.amazonaws.com/funnycatisfunny.mp4"
}

我曾经遇到过由于 CORS 导致的问题,但在指定以下配置后这些问题就消失了:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

我认为问题可能是由于 S3 存储桶缺少策略造成的,因此我指定了一个:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:Put*",
            "Resource": "arn:aws:s3:::my-bucket/*"
        }
    ]
}

这也没有改变事情。

我无法理解这个问题。非常感谢任何帮助。

更新:事实证明,我将文件放置在错误的 url(即存储桶 url)处,而应该始终将文件放置到 bucketurl/filename。调整这个允许我将文件上传到 S3。但是,一旦我再次阻止公共访问,我就会像以前一样收到 403 Forbidden

javascript ajax amazon-s3 http-status-code-403 http-status-code-400
1个回答
0
投票

我一直在尝试使用

S3Client
中的
@aws-sdk/client-s3
PutObjectCommand
来上传对象:

await s3Client.send(new PutObjectCommand(
{
  Bucket: string;
  Key: string;
  Body: File;
  Metadata: { string: string };
}
))

我也收到了

400 Bad Request
,结果发现我试图发送的
MetaData
太大了。

© www.soinside.com 2019 - 2024. All rights reserved.