|
1 | 1 | /* |
2 | | - * jQuery File Upload Plugin 5.8.1 |
| 2 | + * jQuery File Upload Plugin 5.10.0 |
3 | 3 | * https://github.com/blueimp/jQuery-File-Upload |
4 | 4 | * |
5 | 5 | * Copyright 2010, Sebastian Tschan |
|
10 | 10 | */ |
11 | 11 |
|
12 | 12 | /*jslint nomen: true, unparam: true, regexp: true */ |
13 | | -/*global define, window, document, XMLHttpRequestUpload, Blob, File, FormData, location */ |
| 13 | +/*global define, window, document, Blob, FormData, location */ |
14 | 14 |
|
15 | 15 | (function (factory) { |
16 | 16 | 'use strict'; |
|
27 | 27 | }(function ($) { |
28 | 28 | 'use strict'; |
29 | 29 |
|
| 30 | + // The FileReader API is not actually used, but works as feature detection, |
| 31 | + // as e.g. Safari supports XHR file uploads via the FormData API, |
| 32 | + // but not non-multipart XHR file uploads: |
| 33 | + $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); |
| 34 | + $.support.xhrFormDataFileUpload = !!window.FormData; |
| 35 | + |
30 | 36 | // The fileupload widget listens for change events on file input fields defined |
31 | 37 | // via fileInput setting and paste or drop events of the given dropZone. |
32 | 38 | // In addition to the default jQuery Widget methods, the fileupload widget |
|
57 | 63 | replaceFileInput: true, |
58 | 64 | // The parameter name for the file form data (the request argument name). |
59 | 65 | // If undefined or empty, the name property of the file input field is |
60 | | - // used, or "files[]" if the file input name property is also empty: |
| 66 | + // used, or "files[]" if the file input name property is also empty, |
| 67 | + // can be a string or an array of strings: |
61 | 68 | paramName: undefined, |
62 | 69 | // By default, each file of a selection is uploaded using an individual |
63 | 70 | // request for XHR type uploads. Set to false to upload file |
|
165 | 172 | }, |
166 | 173 |
|
167 | 174 | // A list of options that require a refresh after assigning a new value: |
168 | | - _refreshOptionsList: ['namespace', 'dropZone', 'fileInput'], |
| 175 | + _refreshOptionsList: [ |
| 176 | + 'namespace', |
| 177 | + 'dropZone', |
| 178 | + 'fileInput', |
| 179 | + 'multipart', |
| 180 | + 'forceIframeTransport' |
| 181 | + ], |
169 | 182 |
|
170 | 183 | _isXHRUpload: function (options) { |
171 | | - var undef = 'undefined'; |
172 | 184 | return !options.forceIframeTransport && |
173 | | - typeof XMLHttpRequestUpload !== undef && typeof File !== undef && |
174 | | - (!options.multipart || typeof FormData !== undef); |
| 185 | + ((!options.multipart && $.support.xhrFileUpload) || |
| 186 | + $.support.xhrFormDataFileUpload); |
175 | 187 | }, |
176 | 188 |
|
177 | 189 | _getFormData: function (options) { |
|
245 | 257 |
|
246 | 258 | _initXHRData: function (options) { |
247 | 259 | var formData, |
248 | | - file = options.files[0]; |
249 | | - if (!options.multipart || options.blob) { |
| 260 | + file = options.files[0], |
| 261 | + // Ignore non-multipart setting if not supported: |
| 262 | + multipart = options.multipart || !$.support.xhrFileUpload, |
| 263 | + paramName = options.paramName[0]; |
| 264 | + if (!multipart || options.blob) { |
250 | 265 | // For non-multipart uploads and chunked uploads, |
251 | 266 | // file meta data is not part of the request body, |
252 | 267 | // so we transmit this data as part of the HTTP headers. |
|
262 | 277 | // Non-chunked non-multipart upload: |
263 | 278 | options.contentType = file.type; |
264 | 279 | options.data = file; |
265 | | - } else if (!options.multipart) { |
| 280 | + } else if (!multipart) { |
266 | 281 | // Chunked non-multipart upload: |
267 | 282 | options.contentType = 'application/octet-stream'; |
268 | 283 | options.data = options.blob; |
269 | 284 | } |
270 | 285 | } |
271 | | - if (options.multipart && typeof FormData !== 'undefined') { |
| 286 | + if (multipart && $.support.xhrFormDataFileUpload) { |
272 | 287 | if (options.postMessage) { |
273 | 288 | // window.postMessage does not allow sending FormData |
274 | 289 | // objects, so we just add the File/Blob objects to |
|
277 | 292 | formData = this._getFormData(options); |
278 | 293 | if (options.blob) { |
279 | 294 | formData.push({ |
280 | | - name: options.paramName, |
| 295 | + name: paramName, |
281 | 296 | value: options.blob |
282 | 297 | }); |
283 | 298 | } else { |
284 | 299 | $.each(options.files, function (index, file) { |
285 | 300 | formData.push({ |
286 | | - name: options.paramName, |
| 301 | + name: options.paramName[index] || paramName, |
287 | 302 | value: file |
288 | 303 | }); |
289 | 304 | }); |
|
298 | 313 | }); |
299 | 314 | } |
300 | 315 | if (options.blob) { |
301 | | - formData.append(options.paramName, options.blob, file.name); |
| 316 | + formData.append(paramName, options.blob, file.name); |
302 | 317 | } else { |
303 | 318 | $.each(options.files, function (index, file) { |
304 | 319 | // File objects are also Blob instances. |
305 | 320 | // This check allows the tests to run with |
306 | 321 | // dummy objects: |
307 | 322 | if (file instanceof Blob) { |
308 | | - formData.append(options.paramName, file, file.name); |
| 323 | + formData.append( |
| 324 | + options.paramName[index] || paramName, |
| 325 | + file, |
| 326 | + file.name |
| 327 | + ); |
309 | 328 | } |
310 | 329 | }); |
311 | 330 | } |
|
349 | 368 | } |
350 | 369 | }, |
351 | 370 |
|
| 371 | + _getParamName: function (options) { |
| 372 | + var fileInput = $(options.fileInput), |
| 373 | + paramName = options.paramName; |
| 374 | + if (!paramName) { |
| 375 | + paramName = []; |
| 376 | + fileInput.each(function () { |
| 377 | + var input = $(this), |
| 378 | + name = input.prop('name') || 'files[]', |
| 379 | + i = (input.prop('files') || [1]).length; |
| 380 | + while (i) { |
| 381 | + paramName.push(name); |
| 382 | + i -= 1; |
| 383 | + } |
| 384 | + }); |
| 385 | + if (!paramName.length) { |
| 386 | + paramName = [fileInput.prop('name') || 'files[]']; |
| 387 | + } |
| 388 | + } else if (!$.isArray(paramName)) { |
| 389 | + paramName = [paramName]; |
| 390 | + } |
| 391 | + return paramName; |
| 392 | + }, |
| 393 | + |
352 | 394 | _initFormSettings: function (options) { |
353 | 395 | // Retrieve missing options from the input field and the |
354 | 396 | // associated form, if available: |
355 | 397 | if (!options.form || !options.form.length) { |
356 | 398 | options.form = $(options.fileInput.prop('form')); |
357 | 399 | } |
358 | | - if (!options.paramName) { |
359 | | - options.paramName = options.fileInput.prop('name') || |
360 | | - 'files[]'; |
361 | | - } |
| 400 | + options.paramName = this._getParamName(options); |
362 | 401 | if (!options.url) { |
363 | 402 | options.url = options.form.prop('action') || location.href; |
364 | 403 | } |
|
621 | 660 | result = true, |
622 | 661 | options = $.extend({}, this.options, data), |
623 | 662 | limit = options.limitMultiFileUploads, |
| 663 | + paramName = this._getParamName(options), |
| 664 | + paramNameSet, |
| 665 | + paramNameSlice, |
624 | 666 | fileSet, |
625 | 667 | i; |
626 | 668 | if (!(options.singleFileUploads || limit) || |
627 | 669 | !this._isXHRUpload(options)) { |
628 | 670 | fileSet = [data.files]; |
| 671 | + paramNameSet = [paramName]; |
629 | 672 | } else if (!options.singleFileUploads && limit) { |
630 | 673 | fileSet = []; |
| 674 | + paramNameSet = []; |
631 | 675 | for (i = 0; i < data.files.length; i += limit) { |
632 | 676 | fileSet.push(data.files.slice(i, i + limit)); |
| 677 | + paramNameSlice = paramName.slice(i, i + limit); |
| 678 | + if (!paramNameSlice.length) { |
| 679 | + paramNameSlice = paramName; |
| 680 | + } |
| 681 | + paramNameSet.push(paramNameSlice); |
633 | 682 | } |
| 683 | + } else { |
| 684 | + paramNameSet = paramName; |
634 | 685 | } |
635 | 686 | data.originalFiles = data.files; |
636 | 687 | $.each(fileSet || data.files, function (index, element) { |
637 | | - var files = fileSet ? element : [element], |
638 | | - newData = $.extend({}, data, {files: files}); |
| 688 | + var newData = $.extend({}, data); |
| 689 | + newData.files = fileSet ? element : [element]; |
| 690 | + newData.paramName = paramNameSet[index]; |
639 | 691 | newData.submit = function () { |
640 | 692 | newData.jqXHR = this.jqXHR = |
641 | 693 | (that._trigger('submit', e, this) !== false) && |
|
748 | 800 |
|
749 | 801 | _initEventHandlers: function () { |
750 | 802 | var ns = this.options.namespace; |
751 | | - this.options.dropZone |
752 | | - .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) |
753 | | - .bind('drop.' + ns, {fileupload: this}, this._onDrop) |
754 | | - .bind('paste.' + ns, {fileupload: this}, this._onPaste); |
| 803 | + if (this._isXHRUpload(this.options)) { |
| 804 | + this.options.dropZone |
| 805 | + .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) |
| 806 | + .bind('drop.' + ns, {fileupload: this}, this._onDrop) |
| 807 | + .bind('paste.' + ns, {fileupload: this}, this._onPaste); |
| 808 | + } |
755 | 809 | this.options.fileInput |
756 | 810 | .bind('change.' + ns, {fileupload: this}, this._onChange); |
757 | 811 | }, |
|
0 commit comments