Upload files to Amazon S3 With Dropzone.js issue

后端 未结 3 1877
野趣味
野趣味 2021-02-08 06:08

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

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

https://devcenter.heroku.com/articl

3条回答
  •  [愿得一人]
    2021-02-08 06:23

    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.

    The architecture

    So, basically,

    1. You're signing a PUT upload-able URL, thus you MUST hijack the xhr.send function as you already mentioned.
    2. 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.

    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.

    Demo

提交回复
热议问题