Selaa lähdekoodia

Merge branch 'master' of https://github.com/transloadit/uppy

Alexander Zaytsev 7 vuotta sitten
vanhempi
commit
04de1b3e71

+ 1 - 1
package.json

@@ -21,7 +21,7 @@
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   "author": "",
-  "license": "ISC",
+  "license": "MIT",
   "bugs": {
     "url": "https://github.com/transloadit/uppy/issues"
   },

+ 10 - 1
src/core/Core.js

@@ -293,6 +293,15 @@ class Uppy {
     })
   }
 
+  /**
+   * Get a file object.
+   *
+   * @param {string} fileID The ID of the file object to return.
+   */
+  getFile (fileID) {
+    return this.getState().files[fileID]
+  }
+
   removeFile (fileID) {
     const updatedFiles = Object.assign({}, this.getState().files)
     delete updatedFiles[fileID]
@@ -676,7 +685,7 @@ class Uppy {
 
       const waitingFileIDs = []
       Object.keys(this.state.files).forEach((fileID) => {
-        const file = this.state.files[fileID]
+        const file = this.getFile(fileID)
         // TODO: replace files[file].isRemote with some logic
         //
         // filter files that are now yet being uploaded / haven’t been uploaded

+ 2 - 2
src/index.js

@@ -24,7 +24,7 @@ const MetaData = require('./plugins/MetaData.js')
 
 // Uploaders
 const Tus10 = require('./plugins/Tus10')
-const Multipart = require('./plugins/Multipart')
+const XHRUpload = require('./plugins/XHRUpload')
 const Transloadit = require('./plugins/Transloadit')
 
 module.exports = {
@@ -39,7 +39,7 @@ module.exports = {
   Instagram,
   FileInput,
   Tus10,
-  Multipart,
+  XHRUpload,
   Transloadit,
   Dashboard,
   MetaData,

+ 3 - 1
src/plugins/Transloadit/Client.js

@@ -27,7 +27,9 @@ module.exports = class Client {
       data.append('signature', signature)
     }
 
-    data.append('fields', JSON.stringify(fields))
+    Object.keys(fields).forEach((key) => {
+      data.append(key, fields[key])
+    })
     data.append('tus_num_expected_upload_files', expectedFiles)
 
     return fetch(`${this.apiUrl}/assemblies`, {

+ 4 - 8
src/plugins/Transloadit/index.js

@@ -78,7 +78,7 @@ module.exports = class Transloadit extends Plugin {
     const options = this.opts
     return Promise.all(
       fileIDs.map((fileID) => {
-        const file = this.getFile(fileID)
+        const file = this.core.getFile(fileID)
         const promise = Promise.resolve(options.getAssemblyOptions(file, options))
         return promise.then((assemblyOptions) => {
           this.validateParams(assemblyOptions.params)
@@ -255,10 +255,6 @@ module.exports = class Transloadit extends Plugin {
     })
   }
 
-  getFile (fileID) {
-    return this.core.state.files[fileID]
-  }
-
   prepareUpload (fileIDs) {
     fileIDs.forEach((fileID) => {
       this.core.emit('core:preprocess-progress', fileID, {
@@ -289,7 +285,7 @@ module.exports = class Transloadit extends Plugin {
     // If we don't have to wait for encoding metadata or results, we can close
     // the socket immediately and finish the upload.
     if (!this.shouldWait()) {
-      const file = this.getFile(fileID)
+      const file = this.core.getFile(fileID)
       const socket = this.socket[file.assembly]
       socket.close()
       return
@@ -304,7 +300,7 @@ module.exports = class Transloadit extends Plugin {
       })
 
       const onAssemblyFinished = (assembly) => {
-        const file = this.getFile(fileID)
+        const file = this.core.getFile(fileID)
         // An assembly for a different upload just finished. We can ignore it.
         if (assembly.assembly_id !== file.transloadit.assembly) {
           return
@@ -324,7 +320,7 @@ module.exports = class Transloadit extends Plugin {
       }
 
       const onAssemblyError = (assembly, error) => {
-        const file = this.getFile(fileID)
+        const file = this.core.getFile(fileID)
         // An assembly for a different upload just errored. We can ignore it.
         if (assembly.assembly_id !== file.transloadit.assembly) {
           return

+ 24 - 8
src/plugins/Tus10.js

@@ -131,6 +131,7 @@ module.exports = class Tus10 extends Plugin {
       }
 
       optsTus.onProgress = (bytesUploaded, bytesTotal) => {
+        this.onReceiveUploadUrl(file, upload.url)
         this.core.emitter.emit('core:upload-progress', {
           uploader: this,
           id: file.id,
@@ -249,6 +250,26 @@ module.exports = class Tus10 extends Plugin {
     })
   }
 
+  getFile (fileID) {
+    return this.core.state.files[fileID]
+  }
+
+  onReceiveUploadUrl (file, uploadURL) {
+    const currentFile = this.getFile(file.id)
+    // Only do the update if we didn't have an upload URL yet.
+    if (!currentFile.tus || currentFile.tus.uploadUrl !== uploadURL) {
+      const newFile = Object.assign({}, currentFile, {
+        tus: Object.assign({}, currentFile.tus, {
+          uploadUrl: uploadURL
+        })
+      })
+      const files = Object.assign({}, this.core.state.files, {
+        [currentFile.id]: newFile
+      })
+      this.core.setState({ files })
+    }
+  }
+
   onFileRemove (fileID, cb) {
     this.core.emitter.on('core:file-remove', (targetFileID) => {
       if (fileID === targetFileID) cb()
@@ -266,16 +287,14 @@ module.exports = class Tus10 extends Plugin {
 
   onPauseAll (fileID, cb) {
     this.core.emitter.on('core:pause-all', () => {
-      const files = this.core.getState().files
-      if (!files[fileID]) return
+      if (!this.core.getFile(fileID)) return
       cb()
     })
   }
 
   onResumeAll (fileID, cb) {
     this.core.emitter.on('core:resume-all', () => {
-      const files = this.core.getState().files
-      if (!files[fileID]) return
+      if (!this.core.getFile(fileID)) return
       cb()
     })
   }
@@ -300,10 +319,7 @@ module.exports = class Tus10 extends Plugin {
     }
 
     this.core.log('Tus is uploading...')
-    const filesToUpload = fileIDs.map(getFile, this)
-    function getFile (fileID) {
-      return this.core.state.files[fileID]
-    }
+    const filesToUpload = fileIDs.map((fileID) => this.core.getFile(fileID))
 
     this.uploadFiles(filesToUpload)
 

+ 51 - 32
src/plugins/Multipart.js → src/plugins/XHRUpload.js

@@ -2,19 +2,24 @@ const Plugin = require('./Plugin')
 const UppySocket = require('../core/UppySocket')
 const Utils = require('../core/Utils')
 
-module.exports = class Multipart extends Plugin {
+module.exports = class XHRUpload extends Plugin {
   constructor (core, opts) {
     super(core, opts)
     this.type = 'uploader'
-    this.id = 'Multipart'
-    this.title = 'Multipart'
+    this.id = 'XHRUpload'
+    this.title = 'XHRUpload'
 
     // Default options
     const defaultOptions = {
+      formData: true,
       fieldName: 'files[]',
+      metaFields: null,
       responseUrlFieldName: 'url',
       bundle: true,
-      headers: {}
+      headers: {},
+      getResponseData (xhr) {
+        return JSON.parse(xhr.response)
+      }
     }
 
     // Merge default options with the ones set by user
@@ -23,25 +28,38 @@ module.exports = class Multipart extends Plugin {
     this.handleUpload = this.handleUpload.bind(this)
   }
 
-  upload (file, current, total) {
-    this.core.log(`uploading ${current} of ${total}`)
-    return new Promise((resolve, reject) => {
-      // turn file into an array so we can use bundle
-      // if (!this.opts.bundle) {
-      //   files = [files[current]]
-      // }
+  createFormDataUpload (file, opts) {
+    const formPost = new FormData()
 
-      // for (let i in files) {
-      //   formPost.append(this.opts.fieldName, files[i])
-      // }
+    const metaFields = Array.isArray(opts.metaFields)
+      ? opts.metaFields
+      // Send along all fields by default.
+      : Object.keys(file.meta)
+    metaFields.forEach((item) => {
+      formPost.append(item, file.meta[item])
+    })
 
-      const formPost = new FormData()
-      formPost.append(this.opts.fieldName, file.data)
+    formPost.append(opts.fieldName, file.data)
 
-      Object.keys(file.meta).forEach((item) => {
-        // console.log(file.meta, file.meta[item])
-        formPost.append(item, file.meta[item])
-      })
+    return formPost
+  }
+
+  createBareUpload (file, opts) {
+    return file.data
+  }
+
+  upload (file, current, total) {
+    const opts = Object.assign({},
+      this.opts,
+      this.core.state.xhrUpload || {},
+      file.xhrUpload || {}
+    )
+
+    this.core.log(`uploading ${current} of ${total}`)
+    return new Promise((resolve, reject) => {
+      const data = opts.formData
+        ? this.createFormDataUpload(file, opts)
+        : this.createBareUpload(file, opts)
 
       const xhr = new XMLHttpRequest()
 
@@ -58,8 +76,8 @@ module.exports = class Multipart extends Plugin {
 
       xhr.addEventListener('load', (ev) => {
         if (ev.target.status >= 200 && ev.target.status < 300) {
-          const resp = JSON.parse(xhr.response)
-          const uploadURL = resp[this.opts.responseUrlFieldName]
+          const resp = opts.getResponseData(xhr)
+          const uploadURL = resp[opts.responseUrlFieldName]
 
           this.core.emitter.emit('core:upload-success', file.id, resp, uploadURL)
 
@@ -75,7 +93,7 @@ module.exports = class Multipart extends Plugin {
 
         // var upload = {}
         //
-        // if (this.opts.bundle) {
+        // if (opts.bundle) {
         //   upload = {files: files}
         // } else {
         //   upload = {file: files[current]}
@@ -87,13 +105,13 @@ module.exports = class Multipart extends Plugin {
         return reject('Upload error')
       })
 
-      xhr.open('POST', this.opts.endpoint, true)
+      xhr.open(opts.method.toUpperCase(), opts.endpoint, true)
 
-      Object.keys(this.opts.headers).forEach((header) => {
-        xhr.setRequestHeader(header, this.opts.headers[header])
+      Object.keys(opts.headers).forEach((header) => {
+        xhr.setRequestHeader(header, opts.headers[header])
       })
 
-      xhr.send(formPost)
+      xhr.send(data)
 
       this.core.emitter.on('core:upload-cancel', (fileID) => {
         if (fileID === file.id) {
@@ -112,6 +130,7 @@ module.exports = class Multipart extends Plugin {
   }
 
   uploadRemote (file, current, total) {
+    const opts = Object.assign({}, this.opts, file.xhrUpload || {})
     return new Promise((resolve, reject) => {
       this.core.emitter.emit('core:upload-started', file.id)
 
@@ -123,9 +142,9 @@ module.exports = class Multipart extends Plugin {
           'Content-Type': 'application/json'
         },
         body: JSON.stringify(Object.assign({}, file.remote.body, {
-          endpoint: this.opts.endpoint,
+          endpoint: opts.endpoint,
           size: file.data.size,
-          fieldname: this.opts.fieldName
+          fieldname: opts.fieldName
         }))
       })
       .then((res) => {
@@ -141,7 +160,7 @@ module.exports = class Multipart extends Plugin {
           socket.on('progress', (progressData) => Utils.emitSocketProgress(this, progressData, file))
 
           socket.on('success', (data) => {
-            this.core.emitter.emit('core:upload-success', file.id, data)
+            this.core.emitter.emit('core:upload-success', file.id, data, data.url)
             socket.close()
             return resolve()
           })
@@ -173,11 +192,11 @@ module.exports = class Multipart extends Plugin {
 
   handleUpload (fileIDs) {
     if (fileIDs.length === 0) {
-      this.core.log('Multipart: no files to upload!')
+      this.core.log('XHRUpload: no files to upload!')
       return Promise.resolve()
     }
 
-    this.core.log('Multipart is uploading...')
+    this.core.log('XHRUpload is uploading...')
     const files = fileIDs.map(getFile, this)
     function getFile (fileID) {
       return this.core.state.files[fileID]

+ 4 - 4
website/src/examples/multipart/app.es6

@@ -1,15 +1,15 @@
 const Uppy = require('uppy/lib/core/Core')
 const FileInput = require('uppy/lib/plugins/FileInput')
-const Multipart = require('uppy/lib/plugins/Multipart')
+const XHRUpload = require('uppy/lib/plugins/XHRUpload')
 const ProgressBar = require('uppy/lib/plugins/ProgressBar')
 
 const uppy = new Uppy({debug: true, autoProceed: true})
 
 uppy
   .use(FileInput)
-  .use(Multipart, {
+  .use(XHRUpload, {
     endpoint: '//api2.transloadit.com',
-    bundle: true,
+    formData: true,
     fieldName: 'files[]'
   })
   // by default Uppy removes everything inside target container,
@@ -21,4 +21,4 @@ uppy
   })
   .run()
 
-console.log('Uppy with Formtag and Multipart is loaded')
+console.log('Uppy with Formtag and XHRUpload is loaded')