Blueimp 文件上传 - 直接多次上传到 S3

Posted

技术标签:

【中文标题】Blueimp 文件上传 - 直接多次上传到 S3【英文标题】:Blueimp File Upload - Multiple Uploads Directly to S3 【发布时间】:2016-11-22 21:14:04 【问题描述】:

在过去几天的搜索之后,我发现有近 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 下):

如果启用了 singleFileUploads 选项(这是默认设置),将为 XHR 文件上传选择中的每个文件调用一次 add 回调,data.files 数组长度为 1,因为每个文件都是单独上传的.

这就是我卡住的地方:如果 "each file is uploaded individually" 到 S3,为什么 S3 不这样说?

此外,无论文件数量如何,add 函数都只运行一次。 (我用console.log 声明验证了这一点。)我看到了两个可能的原因:

    插件在一次失败后停止进一步的提交。 插件未单独提交文件(无论出于何种原因)。

是我的代码不正确,是我在插件中遗漏了一个选项,还是插件不支持多次直接上传到 S3?


更新

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

【问题讨论】:

你找到这个问题的答案了吗? 不幸的是,没有。我们只需要禁用多个文件上传。 好的,不用担心,我已经开始为此提供赏金,因为我的要求必须支持多个文件上传,并且您已经准确地描述了我的问题。希望我们都能得到答案。 使用文件上传插件是要求的一部分吗? 看起来您已将data.submit(); //why is this submitting all files at once? 放入成功回调中 【参考方案1】:

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

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

documentation for the singleFileUploads option 声明如下:

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

虽然documentation for the forceIframeTransport option 声明如下:

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

因此,解决方案是enable CORS on the S3 bucket 并且启用forceIframeTransport 选项。

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

【讨论】:

感谢您及时详细地回复 Sebastian 的电子邮件。 Greenracoon23你能检查并确认解决方案吗? 有效!谢谢!具体来说,它是&lt;AllowedOrigin&gt;CORSRule。顺便说一句,你的插件很棒。 好消息@GreenRaccoon23 - 很高兴听到这个长期存在的问题现在有了解决方案。我已将赏金授予 Seb。 不是还要设置limitMultiFileUploads: 1吗?否则我仍然只看到一个帖子请求。

以上是关于Blueimp 文件上传 - 直接多次上传到 S3的主要内容,如果未能解决你的问题,请参考以下文章

Jquery Blueimp 文件上传回调

通过 https 上传多个文件时 blueimp jquery 文件上传挂起

Yii2的BlueImp文件上传小工具

上传的文件的临时名称没有进入 blueimp jQuery 文件上传

BlueImp 文件上传“错误:方法不允许” - Laravel 4 路由问题

Blueimp 上传插件进度条错误