Quellcode durchsuchen

Merge pull request #1150 from transloadit/feature/xhr-response-type

xhr-upload: Add `responseType` option
Renée Kooi vor 6 Jahren
Ursprung
Commit
821cb16164

+ 10 - 7
examples/aws-presigned-url/serve.js

@@ -26,20 +26,23 @@ b.transform(aliasify, {
 })
 })
 
 
 function bundle () {
 function bundle () {
-  return b.bundle()
-    .pipe(createWriteStream(path.join(__dirname, './bundle.js')))
+  return b.bundle((err, data) => {
+    if (err) console.error(err.stack)
+    else console.log('bundle complete')
+  }).pipe(createWriteStream(path.join(__dirname, './bundle.js')))
 }
 }
 
 
 b.on('log', console.log)
 b.on('log', console.log)
 b.on('update', bundle)
 b.on('update', bundle)
 b.on('error', console.error)
 b.on('error', console.error)
 
 
-bundle()
-
 fs.createReadStream(path.join(__dirname, '../../packages/uppy/dist/uppy.min.css'))
 fs.createReadStream(path.join(__dirname, '../../packages/uppy/dist/uppy.min.css'))
   .pipe(fs.createWriteStream(path.join(__dirname, './uppy.min.css')))
   .pipe(fs.createWriteStream(path.join(__dirname, './uppy.min.css')))
 
 
-// Start the PHP delevopment server.
-spawn('php', ['-S', `localhost:${port}`], {
-  stdio: 'inherit'
+console.log('bundling...')
+bundle().on('finish', () => {
+  // Start the PHP delevopment server.
+  spawn('php', ['-S', `localhost:${port}`], {
+    stdio: 'inherit'
+  })
 })
 })

+ 15 - 24
packages/@uppy/aws-s3/src/index.js

@@ -10,6 +10,14 @@ function isXml (xhr) {
   return typeof contentType === 'string' && contentType.toLowerCase() === 'application/xml'
   return typeof contentType === 'string' && contentType.toLowerCase() === 'application/xml'
 }
 }
 
 
+function getXmlValue (source, key) {
+  const start = source.indexOf(`<${key}>`)
+  const end = source.indexOf(`</${key}>`, start)
+  return start !== -1 && end !== -1
+    ? source.slice(start + key.length + 2, end)
+    : ''
+}
+
 function assertServerError (res) {
 function assertServerError (res) {
   if (res && res.error) {
   if (res && res.error) {
     const error = new Error(res.message)
     const error = new Error(res.message)
@@ -167,6 +175,7 @@ module.exports = class AwsS3 extends Plugin {
       responseUrlFieldName: 'location',
       responseUrlFieldName: 'location',
       timeout: this.opts.timeout,
       timeout: this.opts.timeout,
       limit: this.opts.limit,
       limit: this.opts.limit,
+      responseType: 'text',
       // Get the response data from a successful XMLHttpRequest instance.
       // Get the response data from a successful XMLHttpRequest instance.
       // `content` is the S3 response as a string.
       // `content` is the S3 response as a string.
       // `xhr` is the XMLHttpRequest instance.
       // `xhr` is the XMLHttpRequest instance.
@@ -196,31 +205,13 @@ module.exports = class AwsS3 extends Plugin {
           return { location: xhr.responseURL.replace(/\?.*$/, '') }
           return { location: xhr.responseURL.replace(/\?.*$/, '') }
         }
         }
 
 
-        let getValue = () => ''
-        if (xhr.responseXML) {
-          getValue = (key) => {
-            const el = xhr.responseXML.querySelector(key)
-            return el ? el.textContent : ''
-          }
-        }
-
-        if (xhr.responseText) {
-          getValue = (key) => {
-            const start = xhr.responseText.indexOf(`<${key}>`)
-            const end = xhr.responseText.indexOf(`</${key}>`)
-            return start !== -1 && end !== -1
-              ? xhr.responseText.slice(start + key.length + 2, end)
-              : ''
-          }
-        }
-
         return {
         return {
           // Some S3 alternatives do not reply with an absolute URL.
           // Some S3 alternatives do not reply with an absolute URL.
           // Eg DigitalOcean Spaces uses /$bucketName/xyz
           // Eg DigitalOcean Spaces uses /$bucketName/xyz
-          location: resolveUrl(xhr.responseURL, getValue('Location')),
-          bucket: getValue('Bucket'),
-          key: getValue('Key'),
-          etag: getValue('ETag')
+          location: resolveUrl(xhr.responseURL, getXmlValue(content, 'Location')),
+          bucket: getXmlValue(content, 'Bucket'),
+          key: getXmlValue(content, 'Key'),
+          etag: getXmlValue(content, 'ETag')
         }
         }
       },
       },
 
 
@@ -232,8 +223,8 @@ module.exports = class AwsS3 extends Plugin {
         if (!isXml(xhr)) {
         if (!isXml(xhr)) {
           return
           return
         }
         }
-        const error = xhr.responseXML.querySelector('Error > Message')
-        return new Error(error.textContent)
+        const error = getXmlValue(content, 'Message')
+        return new Error(error)
       }
       }
     })
     })
   }
   }

+ 6 - 4
packages/@uppy/xhr-upload/src/index.js

@@ -47,6 +47,7 @@ module.exports = class XHRUpload extends Plugin {
       timeout: 30 * 1000,
       timeout: 30 * 1000,
       limit: 0,
       limit: 0,
       withCredentials: false,
       withCredentials: false,
+      responseType: '',
       /**
       /**
        * @typedef respObj
        * @typedef respObj
        * @property {string} responseText
        * @property {string} responseText
@@ -201,6 +202,8 @@ module.exports = class XHRUpload extends Plugin {
       })
       })
 
 
       const xhr = new XMLHttpRequest()
       const xhr = new XMLHttpRequest()
+      xhr.responseType = opts.responseType
+
       const id = cuid()
       const id = cuid()
 
 
       xhr.upload.addEventListener('loadstart', (ev) => {
       xhr.upload.addEventListener('loadstart', (ev) => {
@@ -271,7 +274,7 @@ module.exports = class XHRUpload extends Plugin {
       })
       })
 
 
       xhr.open(opts.method.toUpperCase(), opts.endpoint, true)
       xhr.open(opts.method.toUpperCase(), opts.endpoint, true)
-
+      // IE10 does not allow setting `withCredentials` before `open()` is called.
       xhr.withCredentials = opts.withCredentials
       xhr.withCredentials = opts.withCredentials
 
 
       Object.keys(opts.headers).forEach((header) => {
       Object.keys(opts.headers).forEach((header) => {
@@ -357,8 +360,7 @@ module.exports = class XHRUpload extends Plugin {
       })
       })
 
 
       const xhr = new XMLHttpRequest()
       const xhr = new XMLHttpRequest()
-
-      xhr.withCredentials = this.opts.withCredentials
+      xhr.responseType = this.opts.responseType
 
 
       const timer = this.createProgressTimeout(this.opts.timeout, (error) => {
       const timer = this.createProgressTimeout(this.opts.timeout, (error) => {
         xhr.abort()
         xhr.abort()
@@ -422,7 +424,7 @@ module.exports = class XHRUpload extends Plugin {
       })
       })
 
 
       xhr.open(method.toUpperCase(), endpoint, true)
       xhr.open(method.toUpperCase(), endpoint, true)
-
+      // IE10 does not allow setting `withCredentials` before `open()` is called.
       xhr.withCredentials = this.opts.withCredentials
       xhr.withCredentials = this.opts.withCredentials
 
 
       Object.keys(this.opts.headers).forEach((header) => {
       Object.keys(this.opts.headers).forEach((header) => {

+ 5 - 0
website/src/docs/xhrupload.md

@@ -173,6 +173,10 @@ The default for the timeout is 30 seconds.
 
 
 Limit the amount of uploads going on at the same time. Setting this to `0` means there is no limit on concurrent uploads.
 Limit the amount of uploads going on at the same time. Setting this to `0` means there is no limit on concurrent uploads.
 
 
+### `responseType: ''`
+
+The response type expected from the server, determining how the `xhr.response` property should be filled. The `xhr.response` property can be accessed in a custom [`getResponseData()`](#getResponseData-responseText-response) callback. This option sets the [`XMLHttpRequest.responseType][XHR.responseType] property. Only '', 'text', 'arraybuffer', 'blob' and 'document' are widely supported by browsers, so it's recommended to use one of those. The default is the empty string, which is equivalent to 'text' for the `xhr.response` property.
+
 ### `withCredentials: false`
 ### `withCredentials: false`
 
 
 Indicates whether or not cross-site Access-Control requests should be made using credentials.
 Indicates whether or not cross-site Access-Control requests should be made using credentials.
@@ -253,5 +257,6 @@ move_uploaded_file($file_path, './img/' . basename($file_name)); // save the fil
 
 
 [FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
 [FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
 [XHR.timeout]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout
 [XHR.timeout]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout
+[XHR.responseType]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
 [PHP.file-upload]: https://secure.php.net/manual/en/features.file-upload.php
 [PHP.file-upload]: https://secure.php.net/manual/en/features.file-upload.php
 [PHP.multiple]: https://secure.php.net/manual/en/features.file-upload.multiple.php
 [PHP.multiple]: https://secure.php.net/manual/en/features.file-upload.multiple.php