【问题标题】:dropzone.js upload to Amazon S3 produces 400 (Bad Request) for 3rd+ uploadsdropzone.js 上传到 Amazon S3 为第 3 次以上上传产生 400(错误请求)
【发布时间】:2019-11-25 11:41:01
【问题描述】:

我正在尝试实现一个 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 中的默认值,但我不确定为什么。

我什至尝试在调用凭据以从服务器获取配置值之前使用正确的值初始化我的变量。

感谢任何帮助。

【问题讨论】:

    标签: amazon-web-services amazon-s3 aws-sdk dropzone.js


    【解决方案1】:

    我不确定您的代码为什么会显示这种行为,但对我来说似乎很奇怪的一件事是第一个脚本的结构。您正在通过异步 AJAX 调用在 $(document).ready 函数中获取凭证,但负责 // 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>
    

    【讨论】:

    • 感谢您的提示 - 在我的各种版本中,我在其中一个版本中实例化了一个单独的变量 s3 并在特定对象中设置值。这只是访问aws的一种临时测试方式。最终,这一切都将被 openId 每个用户的凭据所取代。我认为“managedUpload”可能是我的队列问题的一部分,如果我也切换到签名的 url,我可能会解决这个问题。同时,我只是将 parallelUploads 设置为高。
    猜你喜欢
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 1970-01-01
    相关资源
    最近更新 更多