热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Dropzone将文件上传到AmazonS3。js的问题-UploadfilestoAmazonS3WithDropzone.jsissue

ImtryingtouploadfilestoS3serviceusingDropzone.js我正在尝试使用Dropzone.js将文件上传到S3服务Iusethis

I'm trying to upload files to S3 service using Dropzone.js

我正在尝试使用Dropzone.js将文件上传到S3服务

I use this tutorial to upload the files directly from the client:

我使用本教程直接从客户端上传文件:

https://devcenter.heroku.com/articles/s3-upload-node - this tutorial doesn't include the implementation with dropzone js (which was a nightmare)

https://devcenter.heroku.com/articles/s3-upload-node -本教程不包括dropzone js的实现(这是一场噩梦)

The flow is pretty simple:

流程非常简单:

  1. Ask from my server to get signature from amazon
  2. 请求我的服务器从amazon获得签名
  3. get the signed request url + the expected file url from amazon
  4. 从amazon获取签名的请求url +预期的文件url
  5. override dropzone.options.url with the signed request url
  6. 覆盖dropzone.options。带有签名请求url的url
  7. call dropzone.processFile to upload the file to the server
  8. dropzone打电话。processFile将文件上载到服务器

The file is uploaded to the server, until here everything is ok, when I'm trying to view the file (in S3 Bucket interface) it seems like the file was not write correctly and i can't view it.

文件被上传到服务器上,直到这里一切正常,当我试图查看文件(在S3 Bucket接口中)时,似乎文件没有写对,我无法查看它。

According to the source code the file is upload using FormData object.

根据源代码,文件是使用FormData对象上载的。

Dropzone.prototype.submitRequest = function(xhr, formData, files) {
  return xhr.send(formData);
}

if i change the source code from:

如果我将源代码从:

xhr.send(formData)

to

xhr.send(files[0])

Everything works great but i lose to ability to upload multiple files.

一切都很好,但我无法上传多个文件。

This is the dropzone config:

这是dropzone的配置:

{
   url: 'http://signature_url',
   accept: _dropzoneAcceptCallback,
   method: 'put',
   headers: {
      'x-amz-acl': 'public-read',
      'Accept': '*/*',
      'Content-Type': file.type
   },
   clickable: ['.choose-files'],
   autoProcessQueue: false
}

Request HTTP Headers

Hope it's enough :)

希望就足够了:)

Thanks.

谢谢。

3 个解决方案

#1


3  

For someone who might also jumped into this question, I'd like to share my working example as well. Note that I went a step further by taking off my own backend and use AWS Lambda (aka. serverless) instead to do the signing job, the concept is the same though.

对于可能也会进入这个问题的人,我也想分享我的工作例子。注意,我更进一步地去掉了自己的后端并使用AWS Lambda(又名AWS Lambda)。相反,要做签名工作,概念是一样的。

The architecture

demo-pic

So, basically,

所以,基本上,

  1. You're signing a PUT upload-able URL, thus you MUST hijack the xhr.send function as you already mentioned.
  2. 您正在签署一个可上传的URL,因此必须劫持xhr。发送函数,正如您已经提到的。
  3. Instead of relying on Dropzone's FormData to upload multiple files, you can call the processFile inside the accept function. So the upload will starts immediately for each file being accepted and you're able to upload multiple files simultaneously.
  4. 与依赖Dropzone的FormData上传多个文件不同,您可以在accept函数中调用processFile。因此,上传将立即开始为每个文件被接受,你可以同时上传多个文件。

The final client-side code

const vm = this

let optiOns= {
  // The URL will be changed for each new file being processing
  url: '/',

  // Since we're going to do a `PUT` upload to S3 directly
  method: 'put',

  // Hijack the xhr.send since Dropzone always upload file by using formData
  // ref: https://github.com/danialfarid/ng-file-upload/issues/743
  sending (file, xhr) {
    let _send = xhr.send
    xhr.send = () => {
      _send.call(xhr, file)
    }
  },

  // Upload one file at a time since we're using the S3 pre-signed URL scenario
  parallelUploads: 1,
  uploadMultiple: false,

  // Content-Type should be included, otherwise you'll get a signature
  // mismatch error from S3. We're going to update this for each file.
  header: '',

  // We're going to process each file manually (see `accept` below)
  autoProcessQueue: false,

  // Here we request a signed upload URL when a file being accepted
  accept (file, done) {
    lambda.getSignedURL(file)
      .then((url) => {
        file.uploadURL = url
        done()
        // Manually process each file
        setTimeout(() => vm.dropzone.processFile(file))
      })
      .catch((err) => {
        done('Failed to get an S3 signed upload URL', err)
      })
  }
}

// Instantiate Dropzone
this.dropzOne= new Dropzone(this.$el, options)

// Set signed upload URL for each file
vm.dropzone.on('processing', (file) => {
  vm.dropzone.options.url = file.uploadURL
})

The code above has something related to Vue.js, but the concept is actually framework agnostic, you get the idea. For a full working dropzone component example, please have a look at my GitHub repo.

上面的代码与Vue相关。但是这个概念实际上是框架不可知的,你懂的。对于一个完整的工作dropzone组件示例,请查看我的GitHub repo。

Demo

demo-gif

#2


8  

Here's what worked for my on the dropzone init parameters and node S3 signature on the backend:

下面是我在后台的dropzone init参数和节点S3签名的工作原理:

HTML Frontend Code using Dropzone:

使用Dropzone的HTML前端代码:

var myDropzOne= new Dropzone(dropArea, { 
    url:"#",
    dictDefaultMessage: "Drag n drop or tap here",
    method: "PUT",
    uploadMultiple: false,
    paramName: "file",
    maxFiles: 10,
    thumbnailWidth: 80,
    thumbnailHeight: 80,
    parallelUploads: 20,
    autoProcessQueue: true,
    previewTemplate: dropPreviewTemplate,
    //autoQueue: false, // Make sure the files aren't queued until manually added
    previewsContainer: dropPreviewContainer, // Define the container to display the previews
    clickable: true, //".fileinput-button" // Define the element that should be used as click trigger to select files.
    accept: function(file, cb) {
        //override the file name, to use the s3 signature
        //console.log(file);
        var params = {
          fileName: file.name,
          fileType: file.type,
        };

        //path to S3 signature 
        $.getJSON('/uploader', params).done(function(data) {
            //console.log(data);

          if (!data.signedRequest) {
            return cb('Failed to receive an upload url');
          }

          file.signedRequest = data.signedRequest;
          file.finalURL = data.downloadURL;
          cb();
        }).fail(function() {
          return cb('Failed to receive an upload url');
        });
    },
    sending: function(file, xhr) {

        console.log('sending')
        var _send = xhr.send;
        xhr.setRequestHeader('x-amz-acl', 'public-read');
        xhr.send = function() {
            _send.call(xhr, file);
        }

    },
    processing:function(file){

        this.options.url = file.signedRequest;

    }
    });

Here's the libraries I used on the node.js side

这是我在节点上使用的库。js的一面

var Crypto = require("crypto"),
    AWS = require("aws-sdk"),

Here's a sample of the CORS config on S3

这是S3中CORS配置的一个示例。




    *
    PUT
    *

Here's the code to generate the S3 Signature on node.js :

下面是在节点上生成S3签名的代码。js:

        getPolicy:function(req,res)
        {
            var fileId = Crypto.randomBytes(20).toString('hex').toUpperCase();

            var prefix = "bl_";
            var newFileName = prefix+fileId;//req.query.fileName;

            var s3 = new AWS.S3();
            var s3_params = {
                Bucket: BUCKET,
                Key: newFileName,
                Expires: 60,
                ContentType: req.query.fileType,
                ACL: 'public-read'
            };
            s3.getSignedUrl('putObject', s3_params, function(err, data){
                if(err){
                    console.log(err);
                }
                else{
                    var return_data = {
                        signedRequest: data,
                        uploadURL: 'https://'+BUCKET+'.s3.amazonaws.com/'+newFileName,
                        downloadURL: 'http://'+BUCKET+'.s3-website-us-east-1.amazonaws.com/'+newFileName,
                    };
                    res.write(JSON.stringify(return_data));
                    res.end();
                }
            });


        }

Hopefully some of this is helpful.

希望这能有所帮助。

#3


0  

There are two separate items that must be dealt with to upload to S3 - authentication and uploading.

要上载到S3,必须处理两个单独的项目——身份验证和上载。

Auth

Some possibilities, in order of security:

一些可能性,为了安全:

  1. Make your folder public (either via policy or ACL).
  2. 使您的文件夹公开(通过策略或ACL)。
  3. Create a role in IAM that has your preferred limits, and use its keys.
  4. 在IAM中创建一个具有首选限制的角色,并使用它的键。
  5. Use STS to issue temporary credentials, either authenticating yourself or using Federation
  6. 使用STS来颁发临时凭证,或者验证您自己,或者使用联合
  7. Generate a pre-signed upload link for every file.
  8. 为每个文件生成一个预先签名的上传链接。

Generating pre-signed links was demonstrated by Aaron Rau.

Aaron Rau演示了生成预签名链接。

Using STS is conceptually simpler (no need to sign each link), but is somewhat less secure (the same temp credentials can be used elsewhere until they expire).

使用STS在概念上更简单(不需要对每个链接进行签名),但是有点不安全(相同的临时凭证可以在其他地方使用,直到过期)。

If you use federated auth, you can skip the server-side entirely!
Some good tutorials for getting temporary IAM credentials from federated users, are here (for FineUploader, but the mechanism is the same)] and here.

如果您使用联邦授权,您可以完全跳过服务器端!从联邦用户那里获得临时IAM凭据的一些很好的教程在这里(对于FineUploader,但是机制是相同的)和这里。

To generate your own temporary IAM credentials you can use the AWS-SDK. An example in PHP:

要生成自己的临时IAM凭据,可以使用AWS-SDK。PHP中的一个例子:

Server:

服务器:

 'us-east-1', 'version' => 'latest']);
$result = $client->getSessionToken();
header('Content-type: application/json');
echo json_encode($result['Credentials']);

Client:

客户:

let dropzOnesetup= async () => {
    let creds = await fetch('//example.com/auth.php')
        .catch(console.error);

 // If using aws-sdk.js
 AWS.config.credentials = new AWS.Credentials(creds);
Uploading

Either use DropZone natively and amend as needed, or have Dropzone be a front for the aws-sdk.

或者直接使用DropZone并根据需要进行修改,或者让DropZone成为aws-sdk的前端。

To use the aws-sdk

You need to include it

你需要包含它


And then update Dropzone to interact with it (based on this tutorial).

然后更新Dropzone以与之交互(基于本教程)。

let canceled = file => { if (file.s3upload) file.s3upload.abort() }
let optiOns=
    { canceled
    , removedfile: canceled
    , accept (file, done) {
        let params = {Bucket: 'mybucket', Key: file.name, Body: file };
        file.s3upload = new AWS.S3.ManagedUpload({params});
        done();
        }
    }

// 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);
var dz = new Dropzone('#dz', options)

To use DropZone natively

let optiOns= 
    { method: 'put'

    // Have DZ send raw data instead of formData
    , sending (file, xhr) { 
        let _send = xhr.send
        xhr.send = () => _send.call(xhr, file)
        }

    // For STS, if creds is the result of getSessionToken / getFederatedToken
    , headers: { 'x-amz-security-token': creds.SessionToken }

    // Or, if you are using signed URLs (see other answers)
    processing: function(file){ this.options.url = file.signedRequest; }
    async accept (file, done) {
        let url = await fetch('https://example.com/auth.php')
            .catch(err => done('Failed to get an S3 signed upload URL', err));
        file.uploadURL = url
        done()
        }
    }

The above is without testing - have added just the token, but am not sure which headers really needed to be added. Check here, here and here for the docs, and perhaps use FineUploader's implementation as a guide.

上面没有测试——只添加了令牌,但不确定真正需要添加哪些头。在这里、这里和这里检查文档,或者使用FineUploader的实现作为指南。

Hopefully this will help, and if anyone wants to add a pull request for S3 support (as is in FineUploader), I'm sure it will be appreciated.

希望这能有所帮助,如果有人想添加对S3支持的拉取请求(正如FineUploader中所做的那样),我肯定会很感激。


推荐阅读
  • 微软评估和规划(MAP)的工具包介绍及应用实验手册
    本文介绍了微软评估和规划(MAP)的工具包,该工具包是一个无代理工具,旨在简化和精简通过网络范围内的自动发现和评估IT基础设施在多个方案规划进程。工具包支持库存和使用用于SQL Server和Windows Server迁移评估,以及评估服务器的信息最广泛使用微软的技术。此外,工具包还提供了服务器虚拟化方案,以帮助识别未被充分利用的资源和硬件需要成功巩固服务器使用微软的Hyper - V技术规格。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
author-avatar
-Dear-xi
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有