javascript - 400 错误请求上传到带有签名请求的 Amazon S3
问题描述
我正在用 Django 和 React 开发一个 webapp,部署在 Heroku 上,需要文件存储。按照 Heroku 的建议,我使用的是 Amazon S3。但是,我似乎无法从前端将文件上传到我的 S3 存储桶。按照这些说明:https ://devcenter.heroku.com/articles/s3-upload-python ,我首先向后端请求签名请求。(我能够在 Python 中很好地设置它,而使用 boto3 没有任何问题)。然后我使用签名信息尝试将实际文件上传到 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。
解决方案
推荐阅读
- r - 如何编写一个循环来为具有栅格基础的 shapefile 的每个 id 创建裁剪栅格?
- javascript - Redux-form 没有自动接收 onChange
- python - 如何将两个不同长度的列表合并为 Pandas 数据框?
- android - 如何使用 RecyclerView 完成 Adapter 类的活动
- javascript - 什么是`passiveSupported?{被动:真}:假`调用?
- javascript - div显示时如何添加类(活动),隐藏删除类(活动)
- assembly - MSP432 ARM - 使用汇编声明常量数组
- python - 无法获得计数器跟踪双值python
- php - Symfony 4,来自自定义 foo 类(src/Utils/foo.php)中的一个方法,require_one 无效
- xaml - IValueConverter – 将对象作为 ConverterParameter 传递