javascript - Blueimp 文件上传 - 多个直接上传到 S3

标签 javascript jquery file-upload amazon-s3 blueimp

经过过去几天的搜索,我发现近 30 个不同的人在问同样的问题,但我没有找到答案。一对夫妇报告说他们找到了解决方案,但没有提供,所以我希望有人能在这里回答。


使用 blueimp jQuery File Upload ,如何将多个文件直接上传到Amazon S3?

问题:S3 只接受每个请求一个文件

解决方案:使用blueimp jQuery File Upload为每个文件发送单独的请求

障碍:我不知道如何制作 blueimp jQuery File Upload这样做。


解决方案尝试

指南在这里:https://github.com/blueimp/jQuery-File-Upload/wiki/Upload-directly-to-S3

S3 目前需要比指南中显示的更多的表单字段。这是我的代码的精简版:

$(':file').each(function(i, el) {

    var fileInput = $(el);
    var form = fileInput.parents('form:first');

    fileInput.fileupload({
        forceIframeTransport: true,
        autoUpload: true,
        singleFileUploads: true, //default anyway
        add: function(event, data) {
            var files = data.files || [];
            var nextInQueue = files[0]; //this is a queue, not a list
            console.log('nextInQueue:', nextInQueue);
            if (!nextInQueue) return;

            var fileData = {name: nextInQueue.name, mime: nextInQueue.type, size: nextInQueue.size};

            $.ajax({
                url: '/s3stuff',
                type: 'POST',
                dataType: 'json',
                data: {'file': fileData},
                async: false,
                success: function(res) {
                    form.find('input[name="key"]').val(res.key);
                    form.find('input[name="AWSAccessKeyId"]').val(res.AWSAccessKeyId);
                    form.find('input[name="policy"]').val(res.policy);
                    form.find('input[name="signature"]').val(res.signature);
                    form.find('input[name="acl"]').val(res.acl);
                    form.find('input[name="success_action_status"]').val(res.success_action_status);
                    form.find('input[name="Content-Type"]').val(nextInQueue.type);
                    form.attr('action', res.url);

                    data.submit(); //why is this submitting all files at once?
                }
            });
        },
        fail: function(err) {
            console.log('err:', err.stack);
        }
    });
});

错误

当我尝试上传单个文件时,效果很好!但是当我尝试上传多个文件时,S3 返回此 400 错误:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>InvalidArgument</Code>
    <Message>POST requires exactly one file upload per request.</Message>
    <ArgumentName>file</ArgumentName>
    <ArgumentValue>2</ArgumentValue>
</Error>

分析

blueimp jQuery File Upload documentation说这个(在 add 下):

If the singleFileUploads option is enabled (which is the default), the add callback will be called once for each file in the selection for XHR file uploads, with a data.files array length of one, as each file is uploaded individually.

这是我卡住的地方:
如果 “每个文件单独上传” 到 S3,为什么 S3 不这样说?

此外,无论文件数量有多少,add 函数只运行一次。 (我用 console.log 语句验证了这一点。)我看到了 2 个可能的原因:

  1. 该插件会在提交失败后停止进一步提交。
  2. 插件不会单独提交文件(无论出于何种原因)。

我的代码是否不正确,我是否缺少插件中的选项,或者插件是否不支持多个直接上传到 S3?


更新

这是一个用于快速测试的 html 文件: http://pastebin.com/mUBgr4MP

最佳答案

JQuery 文件上传的作者在这里。

文件未单独提交的原因是 forceIframeTransport 选项,在您的示例中该选项设置为 true

documentation for the singleFileUploads option陈述如下:

By default, each file of a selection is uploaded using an individual request for XHR type uploads.

虽然documentation for the forceIframeTransport option陈述如下:

Set this option to true to force iframe transport uploads, even if the browser is capable of XHR file uploads.

所以,解决方案是enable CORS on the S3 bucket启用forceIframeTransport选项。

顺便说一下,大多数集成示例都是用户贡献的(包括 S3 上传指南)。 这是另一个使用 S3 CORS 功能并可能帮助您解决问题的方法(虽然尚未测试): http://pjambet.github.io/blog/direct-upload-to-s3

关于javascript - Blueimp 文件上传 - 多个直接上传到 S3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38467615/

相关文章:

javascript - 无法从动态填充的字符串中 trim 尾随逗号

angular - 上传文件到 S3 但返回 observable

perl - www::curl - 如何上传(发布)大文件

java - 如何在servlet中获取图像数组?

javascript - 胜利图表,如何更改轴和标签颜色

javascript - D3 稳定排序模拟

javascript - 代码以错误的顺序执行

javascript - 禁用 ng repeat 中的按钮

javascript - 在下拉菜单上应用链接但下拉菜单在移动设备上不起作用

php - 脚本执行后如何保存用户在表单页面输入的数据?