蓝色威力文件上传 - 直接向S3多次上传

15

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


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

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

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

障碍:我无法弄清楚如何让blueimp jQuery文件上传做到这一点。


尝试解决办法

指南在这里: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下说:

如果启用单个文件上传选项(默认情况下),则对于XHR文件上传,将为选择的每个文件调用一次添加回调,其中data.files数组长度为1,因为每个文件都是单独上传的。

这就是我卡住的地方:
如果S3将"每个文件都是单独上传",为什么S3说不是?

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

  1. 插件在一个失败后停止进一步提交。
  2. 插件没有单独提交文件(出于任何原因)。

我的代码是否有误,我是否在插件中漏掉了某个选项,或者插件是否不支持多个直接上传到S3?


更新

这里有一个用于快速测试的HTML文件: http://pastebin.com/mUBgr4MP


2
你找到这个问题的答案了吗? - Msencenb
1
很遗憾,不行。我们刚刚不得不禁用多文件上传功能。 - GreenRaccoon23
1
好的,没问题,我已经为此发布了悬赏任务,因为我的要求必须支持多文件上传,而你恰好描述了我的问题。希望我们都能得到答案。 - Msencenb
1
使用文件上传插件是必需的吗? - guest271314
1
所以我开始为此设置调试配置。我的策略是先建立一个独立的HTML + JS页面(无服务器端),然后深入了解数据对象的状态和文件的添加。Blueimp的代码未经缩小,并且我已经可以看到一些方便的控制台输出准备好被取消注释。然而,没有看到您的案例的HTML部分,我有点不清楚。我想在此工作,但您能否帮我简化案例,将其削减为一个独立的HTML和JS设置以说明问题吗? - Vanquished Wombat
显示剩余5条评论
1个回答

11

JQuery文件上传的作者在此。

文件未逐个提交的原因是您的示例中设置了forceIframeTransport选项并将其设置为true

singleFileUploads选项的文档中指出:

默认情况下,每个选择的文件都使用单独的请求上传用于XHR类型上传

forceIframeTransport选项的文档则指出:

将此选项设置为true以强制使用iframe传输上传,即使浏览器能够使用XHR文件上传

所以,解决方案是在S3存储桶上启用CORS不要启用forceIframeTransport选项。

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


可以了!谢谢!具体来说,是 <AllowedOrigin> CORSRule 的问题。顺便说一下,你的插件真棒。 - GreenRaccoon23
2
@GreenRaccoon23,好消息!很高兴听到那个长期存在的问题现在有了解决方案。我已经把赏金授予Seb了。 - Vanquished Wombat
你不也需要设置 limitMultiFileUploads: 1 吗?否则我仍然只能看到一个 POST 请求。 - citynorman
另一个问题是S3 POST没有按预期格式返回json,因此无法正确更新表格... - citynorman
最终的整合示例链接已失效,但是在互联网档案馆中可以找到最新版本(截至2018年4月) - rinogo
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接