Я занимаюсь разработкой веб-приложения на Django и React, развернутого на Heroku, для которого требуется хранилище файлов. В соответствии с рекомендациями Heroku, я использую Amazon S3. Тем не менее, мне кажется, что я не могу загрузить файлы в мое ведро S3 с внешнего интерфейса. Согласно этим инструкциям: https://devcenter.heroku.com/articles/s3-upload-python, я сначала запрашиваю у бэкэнда подписанный запрос. (Я смог установить это в Python без проблем, используя boto3). Затем я использую подписанную информацию, чтобы попытаться загрузить фактический файл на S3. Но при этом я продолжаю получать 400 ошибок Bad Request.
Что также странно, так это то, что мне пришлось включить доступ publi c, чтобы получить ошибку 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)
//...
})
Я предпочитаю использовать топор ios, но я также попробовал следующий код, который использовался в уроке по 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)
//...
})
Учетные данные, используемые для подписания запроса, связаны с пользователем IAM, который имеет полный доступ к S3.
Подписанный запрос, который я получаю от моего 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 / Имя файла . Настройка позволила мне загрузить файл на S3. Однако, как только я снова блокирую доступ publi c, я получаю 403 Forbidden , как и раньше.