amazon-web-services - dropzone.js 上传到 Amazon S3 为第 3 次以上上传产生 400(错误请求)
问题描述
我正在尝试实现一个 dropzone.js 接口来将文件上传到 Amazon S3。我遵循了我在网上找到的几个例子
<html>
<head>
<title>S3 Dropzone</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">
<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.476.0.min.js"></script>
<script language="JavaScript">
var bucket = "test-bucket";
var region = "us-east-2";
var userId = "11111";
$(document).ready(function($) {
$.ajax({
url: "/s3_credentials.php",
data: {},
type: 'POST',
dataType: 'json',
success: function(response) {
bucket = response.Bucket;
region = response.region;
AWS.config.credentials = new AWS.Credentials({
accessKeyId:response.accessKeyId,
secretAccessKey:response.secretAccessKey
});
console.log("credentials response", response, AWS.config.credentials );
}
})
});
// let aws-sdk send events to dropzone.
function sendEvents(file) {
let progress = i => dz.emit('uploadprogress', file, i.loaded * 100 / i.total, i.loaded);
file.s3upload.on('httpUploadProgress', progress);
file.s3upload.send(err => err ? dz.emit('error', file, err) : dz.emit('complete', file));
}
Dropzone.prototype.uploadFiles = files => files.map(sendEvents);
</script>
</head>
<body>
<br><br><br>
<h1 style="text-align: center">ImageUpload to S3Bucket</h1>
<div id="dz" class="dz-clickable dropzone"></div>
<script language="JavaScript">
Dropzone.autoDiscover = false;
let canceled = file => { if (file.s3upload) file.s3upload.abort() }
let options = {
url: '/',
canceled,
removedfile: canceled,
accept(file, done) {
let params = {
Bucket: bucket,
Key: userId + "/" + file.name,
Body: file
};
params.accessKeyId = AWS.config.credentials.accessKeyId;
params.secretAccessKey = AWS.config.credentials.secretAccessKey;
console.log('upload params', params);
file.s3upload = new AWS.S3.ManagedUpload({params});
done();
}
};
var dz = new Dropzone('#dz', options );
</script>
</body>
</html>
凭据脚本很简单:
<?php
$AWSBucket = "dropzone-bucket-test";
$AWSRegion = "us-east-2";
$AWSUserArn = "arn:aws:iam::22222222222:user/test-bucket";
$AWSUserAccessKeyId = "*****************";
$AWSUserSecretAccessKey = "**********************************";
header('Content-Type: application/json');
echo json_encode([
'Bucket' => $AWSBucket,
'accessKeyId' => $AWSUserAccessKeyId,
'secretAccessKey' => $AWSUserSecretAccessKey,
'region' => $AWSRegion,
'userArn' => $AWSUserArn
]);
第 3 次以上 PUT 调用的回复似乎表明该地区正在以某种方式回落到某处的默认值 us-east-1。我的代码都不包含该区域信息,但我在某些 AWS sdk 中将其视为默认值。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AuthorizationHeaderMalformed</Code>
<Message>The authorization header is malformed; the region 'us-east-1' is wrong; expecting 'us-east-2'</Message>
<Region>us-east-2</Region>
<RequestId>********************</RequestId>
<HostId>***********************************************************************=</HostId>
</Error>
它将毫无问题地上传1或2个文件。之后,它似乎开始失败并出现 400 个错误。检查回复,它说该地区是错误的,但我不确定它是如何变成这样的。我假设它回退到 aws-sdk 中的默认值,但我不知道为什么。
在进行凭据调用以从服务器获取配置的值之前,我什至尝试使用正确的值初始化我的变量。
任何帮助表示赞赏。
解决方案
我不确定您的代码为什么会显示这种行为,但对我来说似乎很奇怪的一件事是第一个脚本的结构。您正在$(document).ready
通过异步 AJAX 调用在函数中获取凭证,但负责的代码// let aws-sdk send events to dropzone.
位于 AJAX 的成功处理程序之外,甚至在$(document).ready
函数之外,这意味着它在您的 AWS 开发工具包配置这些凭证之前执行。
我建议将上述代码放入 AJAX 的成功处理程序中。
<script language="JavaScript">
var bucket = "test-bucket";
var region = "us-east-2";
var userId = "11111";
function sendEvents(file) {
let progress = i => dz.emit('uploadprogress', file, i.loaded * 100 / i.total, i.loaded);
file.s3upload.on('httpUploadProgress', progress);
file.s3upload.send(err => err ? dz.emit('error', file, err) : dz.emit('complete', file));
}
$(document).ready(function($) {
$.ajax({
url: "/s3_credentials.php",
data: {},
type: 'POST',
dataType: 'json',
success: function(response) {
bucket = response.Bucket;
region = response.region;
AWS.config.credentials = new AWS.Credentials({
accessKeyId:response.accessKeyId,
secretAccessKey:response.secretAccessKey
});
console.log("credentials response", response, AWS.config.credentials);
// let aws-sdk send events to dropzone.
Dropzone.prototype.uploadFiles = files => files.map(sendEvents);
}
})
});
</script>
推荐阅读
- java - Java / Android Studio / If 语句没有被执行,尽管它符合条件
- mvvm - 如何使客户端 Blazor 中的复选框的双向绑定与视图模型一起使用
- javascript - 添加更多字符时正则表达式不匹配
- reactjs - 当 props 改变时更新 react 根组件
- node.js - SQL 返回的日期不正确
- firebase - 无法确定 React Native Android 中的依赖关系问题
- git - 更新远程服务器上的 git 子模块分支
- scala - ZIO:为什么我会收到“产生了未经检查的错误”。
- dependency-injection - 如何在 .NET Core 中创建同一个单例服务的多个实例?
- subdomain - 由于来自 Fritzbox 的域错误,服务器拒绝请求