我正在尝试实现dropzone.js接口,以将文件上传到AWS 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中的默认值,但我不确定为什么。
我甚至尝试过使用正确的值初始化变量,然后再执行凭据调用以从服务器获取配置的值。
感谢您的帮助。
答案 0 :(得分:0)
我不确定为什么您的代码会显示这种行为,但是对我来说似乎很奇怪的是第一个脚本的结构。您正在通过异步的AJAX调用在$(document).ready
函数中获取凭据,但是负责// let aws-sdk send events to dropzone.
的代码位于AJAX的成功处理程序之外,甚至位于$(document).ready
函数的外部,这意味着它在使用这些凭证配置AWS SDK之前执行。
我建议将提到的代码放入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>