@@ 450-820 (lines=371) @@ | ||
447 | ||
448 | ngFileUpload.version = '12.2.12'; |
|
449 | ||
450 | ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) { |
|
451 | var upload = this; |
|
452 | upload.promisesCount = 0; |
|
453 | ||
454 | this.isResumeSupported = function () { |
|
455 | return window.Blob && window.Blob.prototype.slice; |
|
456 | }; |
|
457 | ||
458 | var resumeSupported = this.isResumeSupported(); |
|
459 | ||
460 | function sendHttp(config) { |
|
461 | config.method = config.method || 'POST'; |
|
462 | config.headers = config.headers || {}; |
|
463 | ||
464 | var deferred = config._deferred = config._deferred || $q.defer(); |
|
465 | var promise = deferred.promise; |
|
466 | ||
467 | function notifyProgress(e) { |
|
468 | if (deferred.notify) { |
|
469 | deferred.notify(e); |
|
470 | } |
|
471 | if (promise.progressFunc) { |
|
472 | $timeout(function () { |
|
473 | promise.progressFunc(e); |
|
474 | }); |
|
475 | } |
|
476 | } |
|
477 | ||
478 | function getNotifyEvent(n) { |
|
479 | if (config._start != null && resumeSupported) { |
|
480 | return { |
|
481 | loaded: n.loaded + config._start, |
|
482 | total: (config._file && config._file.size) || n.total, |
|
483 | type: n.type, config: config, |
|
484 | lengthComputable: true, target: n.target |
|
485 | }; |
|
486 | } else { |
|
487 | return n; |
|
488 | } |
|
489 | } |
|
490 | ||
491 | if (!config.disableProgress) { |
|
492 | config.headers.__setXHR_ = function () { |
|
493 | return function (xhr) { |
|
494 | if (!xhr || !xhr.upload || !xhr.upload.addEventListener) return; |
|
495 | config.__XHR = xhr; |
|
496 | if (config.xhrFn) config.xhrFn(xhr); |
|
497 | xhr.upload.addEventListener('progress', function (e) { |
|
498 | e.config = config; |
|
499 | notifyProgress(getNotifyEvent(e)); |
|
500 | }, false); |
|
501 | //fix for firefox not firing upload progress end, also IE8-9 |
|
502 | xhr.upload.addEventListener('load', function (e) { |
|
503 | if (e.lengthComputable) { |
|
504 | e.config = config; |
|
505 | notifyProgress(getNotifyEvent(e)); |
|
506 | } |
|
507 | }, false); |
|
508 | }; |
|
509 | }; |
|
510 | } |
|
511 | ||
512 | function uploadWithAngular() { |
|
513 | $http(config).then(function (r) { |
|
514 | if (resumeSupported && config._chunkSize && !config._finished && config._file) { |
|
515 | var fileSize = config._file && config._file.size || 0; |
|
516 | notifyProgress({ |
|
517 | loaded: Math.min(config._end, fileSize), |
|
518 | total: fileSize, |
|
519 | config: config, |
|
520 | type: 'progress' |
|
521 | } |
|
522 | ); |
|
523 | upload.upload(config, true); |
|
524 | } else { |
|
525 | if (config._finished) delete config._finished; |
|
526 | deferred.resolve(r); |
|
527 | } |
|
528 | }, function (e) { |
|
529 | deferred.reject(e); |
|
530 | }, function (n) { |
|
531 | deferred.notify(n); |
|
532 | } |
|
533 | ); |
|
534 | } |
|
535 | ||
536 | if (!resumeSupported) { |
|
537 | uploadWithAngular(); |
|
538 | } else if (config._chunkSize && config._end && !config._finished) { |
|
539 | config._start = config._end; |
|
540 | config._end += config._chunkSize; |
|
541 | uploadWithAngular(); |
|
542 | } else if (config.resumeSizeUrl) { |
|
543 | $http.get(config.resumeSizeUrl).then(function (resp) { |
|
544 | if (config.resumeSizeResponseReader) { |
|
545 | config._start = config.resumeSizeResponseReader(resp.data); |
|
546 | } else { |
|
547 | config._start = parseInt((resp.data.size == null ? resp.data : resp.data.size).toString()); |
|
548 | } |
|
549 | if (config._chunkSize) { |
|
550 | config._end = config._start + config._chunkSize; |
|
551 | } |
|
552 | uploadWithAngular(); |
|
553 | }, function (e) { |
|
554 | throw e; |
|
555 | }); |
|
556 | } else if (config.resumeSize) { |
|
557 | config.resumeSize().then(function (size) { |
|
558 | config._start = size; |
|
559 | if (config._chunkSize) { |
|
560 | config._end = config._start + config._chunkSize; |
|
561 | } |
|
562 | uploadWithAngular(); |
|
563 | }, function (e) { |
|
564 | throw e; |
|
565 | }); |
|
566 | } else { |
|
567 | if (config._chunkSize) { |
|
568 | config._start = 0; |
|
569 | config._end = config._start + config._chunkSize; |
|
570 | } |
|
571 | uploadWithAngular(); |
|
572 | } |
|
573 | ||
574 | ||
575 | promise.success = function (fn) { |
|
576 | promise.then(function (response) { |
|
577 | fn(response.data, response.status, response.headers, config); |
|
578 | }); |
|
579 | return promise; |
|
580 | }; |
|
581 | ||
582 | promise.error = function (fn) { |
|
583 | promise.then(null, function (response) { |
|
584 | fn(response.data, response.status, response.headers, config); |
|
585 | }); |
|
586 | return promise; |
|
587 | }; |
|
588 | ||
589 | promise.progress = function (fn) { |
|
590 | promise.progressFunc = fn; |
|
591 | promise.then(null, null, function (n) { |
|
592 | fn(n); |
|
593 | }); |
|
594 | return promise; |
|
595 | }; |
|
596 | promise.abort = promise.pause = function () { |
|
597 | if (config.__XHR) { |
|
598 | $timeout(function () { |
|
599 | config.__XHR.abort(); |
|
600 | }); |
|
601 | } |
|
602 | return promise; |
|
603 | }; |
|
604 | promise.xhr = function (fn) { |
|
605 | config.xhrFn = (function (origXhrFn) { |
|
606 | return function () { |
|
607 | if (origXhrFn) origXhrFn.apply(promise, arguments); |
|
608 | fn.apply(promise, arguments); |
|
609 | }; |
|
610 | })(config.xhrFn); |
|
611 | return promise; |
|
612 | }; |
|
613 | ||
614 | upload.promisesCount++; |
|
615 | if (promise['finally'] && promise['finally'] instanceof Function) { |
|
616 | promise['finally'](function () { |
|
617 | upload.promisesCount--; |
|
618 | }); |
|
619 | } |
|
620 | return promise; |
|
621 | } |
|
622 | ||
623 | this.isUploadInProgress = function () { |
|
624 | return upload.promisesCount > 0; |
|
625 | }; |
|
626 | ||
627 | this.rename = function (file, name) { |
|
628 | file.ngfName = name; |
|
629 | return file; |
|
630 | }; |
|
631 | ||
632 | this.jsonBlob = function (val) { |
|
633 | if (val != null && !angular.isString(val)) { |
|
634 | val = JSON.stringify(val); |
|
635 | } |
|
636 | var blob = new window.Blob([val], {type: 'application/json'}); |
|
637 | blob._ngfBlob = true; |
|
638 | return blob; |
|
639 | }; |
|
640 | ||
641 | this.json = function (val) { |
|
642 | return angular.toJson(val); |
|
643 | }; |
|
644 | ||
645 | function copy(obj) { |
|
646 | var clone = {}; |
|
647 | for (var key in obj) { |
|
648 | if (obj.hasOwnProperty(key)) { |
|
649 | clone[key] = obj[key]; |
|
650 | } |
|
651 | } |
|
652 | return clone; |
|
653 | } |
|
654 | ||
655 | this.isFile = function (file) { |
|
656 | return file != null && (file instanceof window.Blob || (file.flashId && file.name && file.size)); |
|
657 | }; |
|
658 | ||
659 | this.upload = function (config, internal) { |
|
660 | function toResumeFile(file, formData) { |
|
661 | if (file._ngfBlob) return file; |
|
662 | config._file = config._file || file; |
|
663 | if (config._start != null && resumeSupported) { |
|
664 | if (config._end && config._end >= file.size) { |
|
665 | config._finished = true; |
|
666 | config._end = file.size; |
|
667 | } |
|
668 | var slice = file.slice(config._start, config._end || file.size); |
|
669 | slice.name = file.name; |
|
670 | slice.ngfName = file.ngfName; |
|
671 | if (config._chunkSize) { |
|
672 | formData.append('_chunkSize', config._chunkSize); |
|
673 | formData.append('_currentChunkSize', config._end - config._start); |
|
674 | formData.append('_chunkNumber', Math.floor(config._start / config._chunkSize)); |
|
675 | formData.append('_totalSize', config._file.size); |
|
676 | } |
|
677 | return slice; |
|
678 | } |
|
679 | return file; |
|
680 | } |
|
681 | ||
682 | function addFieldToFormData(formData, val, key) { |
|
683 | if (val !== undefined) { |
|
684 | if (angular.isDate(val)) { |
|
685 | val = val.toISOString(); |
|
686 | } |
|
687 | if (angular.isString(val)) { |
|
688 | formData.append(key, val); |
|
689 | } else if (upload.isFile(val)) { |
|
690 | var file = toResumeFile(val, formData); |
|
691 | var split = key.split(','); |
|
692 | if (split[1]) { |
|
693 | file.ngfName = split[1].replace(/^\s+|\s+$/g, ''); |
|
694 | key = split[0]; |
|
695 | } |
|
696 | config._fileKey = config._fileKey || key; |
|
697 | formData.append(key, file, file.ngfName || file.name); |
|
698 | } else { |
|
699 | if (angular.isObject(val)) { |
|
700 | if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key; |
|
701 | ||
702 | val.$$ngfCircularDetection = true; |
|
703 | try { |
|
704 | for (var k in val) { |
|
705 | if (val.hasOwnProperty(k) && k !== '$$ngfCircularDetection') { |
|
706 | var objectKey = config.objectKey == null ? '[i]' : config.objectKey; |
|
707 | if (val.length && parseInt(k) > -1) { |
|
708 | objectKey = config.arrayKey == null ? objectKey : config.arrayKey; |
|
709 | } |
|
710 | addFieldToFormData(formData, val[k], key + objectKey.replace(/[ik]/g, k)); |
|
711 | } |
|
712 | } |
|
713 | } finally { |
|
714 | delete val.$$ngfCircularDetection; |
|
715 | } |
|
716 | } else { |
|
717 | formData.append(key, val); |
|
718 | } |
|
719 | } |
|
720 | } |
|
721 | } |
|
722 | ||
723 | function digestConfig() { |
|
724 | config._chunkSize = upload.translateScalars(config.resumeChunkSize); |
|
725 | config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null; |
|
726 | ||
727 | config.headers = config.headers || {}; |
|
728 | config.headers['Content-Type'] = undefined; |
|
729 | config.transformRequest = config.transformRequest ? |
|
730 | (angular.isArray(config.transformRequest) ? |
|
731 | config.transformRequest : [config.transformRequest]) : []; |
|
732 | config.transformRequest.push(function (data) { |
|
733 | var formData = new window.FormData(), key; |
|
734 | data = data || config.fields || {}; |
|
735 | if (config.file) { |
|
736 | data.file = config.file; |
|
737 | } |
|
738 | for (key in data) { |
|
739 | if (data.hasOwnProperty(key)) { |
|
740 | var val = data[key]; |
|
741 | if (config.formDataAppender) { |
|
742 | config.formDataAppender(formData, key, val); |
|
743 | } else { |
|
744 | addFieldToFormData(formData, val, key); |
|
745 | } |
|
746 | } |
|
747 | } |
|
748 | ||
749 | return formData; |
|
750 | }); |
|
751 | } |
|
752 | ||
753 | if (!internal) config = copy(config); |
|
754 | if (!config._isDigested) { |
|
755 | config._isDigested = true; |
|
756 | digestConfig(); |
|
757 | } |
|
758 | ||
759 | return sendHttp(config); |
|
760 | }; |
|
761 | ||
762 | this.http = function (config) { |
|
763 | config = copy(config); |
|
764 | config.transformRequest = config.transformRequest || function (data) { |
|
765 | if ((window.ArrayBuffer && data instanceof window.ArrayBuffer) || data instanceof window.Blob) { |
|
766 | return data; |
|
767 | } |
|
768 | return $http.defaults.transformRequest[0].apply(this, arguments); |
|
769 | }; |
|
770 | config._chunkSize = upload.translateScalars(config.resumeChunkSize); |
|
771 | config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null; |
|
772 | ||
773 | return sendHttp(config); |
|
774 | }; |
|
775 | ||
776 | this.translateScalars = function (str) { |
|
777 | if (angular.isString(str)) { |
|
778 | if (str.search(/kb/i) === str.length - 2) { |
|
779 | return parseFloat(str.substring(0, str.length - 2) * 1024); |
|
780 | } else if (str.search(/mb/i) === str.length - 2) { |
|
781 | return parseFloat(str.substring(0, str.length - 2) * 1048576); |
|
782 | } else if (str.search(/gb/i) === str.length - 2) { |
|
783 | return parseFloat(str.substring(0, str.length - 2) * 1073741824); |
|
784 | } else if (str.search(/b/i) === str.length - 1) { |
|
785 | return parseFloat(str.substring(0, str.length - 1)); |
|
786 | } else if (str.search(/s/i) === str.length - 1) { |
|
787 | return parseFloat(str.substring(0, str.length - 1)); |
|
788 | } else if (str.search(/m/i) === str.length - 1) { |
|
789 | return parseFloat(str.substring(0, str.length - 1) * 60); |
|
790 | } else if (str.search(/h/i) === str.length - 1) { |
|
791 | return parseFloat(str.substring(0, str.length - 1) * 3600); |
|
792 | } |
|
793 | } |
|
794 | return str; |
|
795 | }; |
|
796 | ||
797 | this.urlToBlob = function(url) { |
|
798 | var defer = $q.defer(); |
|
799 | $http({url: url, method: 'get', responseType: 'arraybuffer'}).then(function (resp) { |
|
800 | var arrayBufferView = new Uint8Array(resp.data); |
|
801 | var type = resp.headers('content-type') || 'image/WebP'; |
|
802 | var blob = new window.Blob([arrayBufferView], {type: type}); |
|
803 | var matches = url.match(/.*\/(.+?)(\?.*)?$/); |
|
804 | if (matches.length > 1) { |
|
805 | blob.name = matches[1]; |
|
806 | } |
|
807 | defer.resolve(blob); |
|
808 | }, function (e) { |
|
809 | defer.reject(e); |
|
810 | }); |
|
811 | return defer.promise; |
|
812 | }; |
|
813 | ||
814 | this.setDefaults = function (defaults) { |
|
815 | this.defaults = defaults || {}; |
|
816 | }; |
|
817 | ||
818 | this.defaults = {}; |
|
819 | this.version = ngFileUpload.version; |
|
820 | } |
|
821 | ||
822 | ]); |
|
823 |
@@ 28-398 (lines=371) @@ | ||
25 | ||
26 | ngFileUpload.version = '12.2.12'; |
|
27 | ||
28 | ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) { |
|
29 | var upload = this; |
|
30 | upload.promisesCount = 0; |
|
31 | ||
32 | this.isResumeSupported = function () { |
|
33 | return window.Blob && window.Blob.prototype.slice; |
|
34 | }; |
|
35 | ||
36 | var resumeSupported = this.isResumeSupported(); |
|
37 | ||
38 | function sendHttp(config) { |
|
39 | config.method = config.method || 'POST'; |
|
40 | config.headers = config.headers || {}; |
|
41 | ||
42 | var deferred = config._deferred = config._deferred || $q.defer(); |
|
43 | var promise = deferred.promise; |
|
44 | ||
45 | function notifyProgress(e) { |
|
46 | if (deferred.notify) { |
|
47 | deferred.notify(e); |
|
48 | } |
|
49 | if (promise.progressFunc) { |
|
50 | $timeout(function () { |
|
51 | promise.progressFunc(e); |
|
52 | }); |
|
53 | } |
|
54 | } |
|
55 | ||
56 | function getNotifyEvent(n) { |
|
57 | if (config._start != null && resumeSupported) { |
|
58 | return { |
|
59 | loaded: n.loaded + config._start, |
|
60 | total: (config._file && config._file.size) || n.total, |
|
61 | type: n.type, config: config, |
|
62 | lengthComputable: true, target: n.target |
|
63 | }; |
|
64 | } else { |
|
65 | return n; |
|
66 | } |
|
67 | } |
|
68 | ||
69 | if (!config.disableProgress) { |
|
70 | config.headers.__setXHR_ = function () { |
|
71 | return function (xhr) { |
|
72 | if (!xhr || !xhr.upload || !xhr.upload.addEventListener) return; |
|
73 | config.__XHR = xhr; |
|
74 | if (config.xhrFn) config.xhrFn(xhr); |
|
75 | xhr.upload.addEventListener('progress', function (e) { |
|
76 | e.config = config; |
|
77 | notifyProgress(getNotifyEvent(e)); |
|
78 | }, false); |
|
79 | //fix for firefox not firing upload progress end, also IE8-9 |
|
80 | xhr.upload.addEventListener('load', function (e) { |
|
81 | if (e.lengthComputable) { |
|
82 | e.config = config; |
|
83 | notifyProgress(getNotifyEvent(e)); |
|
84 | } |
|
85 | }, false); |
|
86 | }; |
|
87 | }; |
|
88 | } |
|
89 | ||
90 | function uploadWithAngular() { |
|
91 | $http(config).then(function (r) { |
|
92 | if (resumeSupported && config._chunkSize && !config._finished && config._file) { |
|
93 | var fileSize = config._file && config._file.size || 0; |
|
94 | notifyProgress({ |
|
95 | loaded: Math.min(config._end, fileSize), |
|
96 | total: fileSize, |
|
97 | config: config, |
|
98 | type: 'progress' |
|
99 | } |
|
100 | ); |
|
101 | upload.upload(config, true); |
|
102 | } else { |
|
103 | if (config._finished) delete config._finished; |
|
104 | deferred.resolve(r); |
|
105 | } |
|
106 | }, function (e) { |
|
107 | deferred.reject(e); |
|
108 | }, function (n) { |
|
109 | deferred.notify(n); |
|
110 | } |
|
111 | ); |
|
112 | } |
|
113 | ||
114 | if (!resumeSupported) { |
|
115 | uploadWithAngular(); |
|
116 | } else if (config._chunkSize && config._end && !config._finished) { |
|
117 | config._start = config._end; |
|
118 | config._end += config._chunkSize; |
|
119 | uploadWithAngular(); |
|
120 | } else if (config.resumeSizeUrl) { |
|
121 | $http.get(config.resumeSizeUrl).then(function (resp) { |
|
122 | if (config.resumeSizeResponseReader) { |
|
123 | config._start = config.resumeSizeResponseReader(resp.data); |
|
124 | } else { |
|
125 | config._start = parseInt((resp.data.size == null ? resp.data : resp.data.size).toString()); |
|
126 | } |
|
127 | if (config._chunkSize) { |
|
128 | config._end = config._start + config._chunkSize; |
|
129 | } |
|
130 | uploadWithAngular(); |
|
131 | }, function (e) { |
|
132 | throw e; |
|
133 | }); |
|
134 | } else if (config.resumeSize) { |
|
135 | config.resumeSize().then(function (size) { |
|
136 | config._start = size; |
|
137 | if (config._chunkSize) { |
|
138 | config._end = config._start + config._chunkSize; |
|
139 | } |
|
140 | uploadWithAngular(); |
|
141 | }, function (e) { |
|
142 | throw e; |
|
143 | }); |
|
144 | } else { |
|
145 | if (config._chunkSize) { |
|
146 | config._start = 0; |
|
147 | config._end = config._start + config._chunkSize; |
|
148 | } |
|
149 | uploadWithAngular(); |
|
150 | } |
|
151 | ||
152 | ||
153 | promise.success = function (fn) { |
|
154 | promise.then(function (response) { |
|
155 | fn(response.data, response.status, response.headers, config); |
|
156 | }); |
|
157 | return promise; |
|
158 | }; |
|
159 | ||
160 | promise.error = function (fn) { |
|
161 | promise.then(null, function (response) { |
|
162 | fn(response.data, response.status, response.headers, config); |
|
163 | }); |
|
164 | return promise; |
|
165 | }; |
|
166 | ||
167 | promise.progress = function (fn) { |
|
168 | promise.progressFunc = fn; |
|
169 | promise.then(null, null, function (n) { |
|
170 | fn(n); |
|
171 | }); |
|
172 | return promise; |
|
173 | }; |
|
174 | promise.abort = promise.pause = function () { |
|
175 | if (config.__XHR) { |
|
176 | $timeout(function () { |
|
177 | config.__XHR.abort(); |
|
178 | }); |
|
179 | } |
|
180 | return promise; |
|
181 | }; |
|
182 | promise.xhr = function (fn) { |
|
183 | config.xhrFn = (function (origXhrFn) { |
|
184 | return function () { |
|
185 | if (origXhrFn) origXhrFn.apply(promise, arguments); |
|
186 | fn.apply(promise, arguments); |
|
187 | }; |
|
188 | })(config.xhrFn); |
|
189 | return promise; |
|
190 | }; |
|
191 | ||
192 | upload.promisesCount++; |
|
193 | if (promise['finally'] && promise['finally'] instanceof Function) { |
|
194 | promise['finally'](function () { |
|
195 | upload.promisesCount--; |
|
196 | }); |
|
197 | } |
|
198 | return promise; |
|
199 | } |
|
200 | ||
201 | this.isUploadInProgress = function () { |
|
202 | return upload.promisesCount > 0; |
|
203 | }; |
|
204 | ||
205 | this.rename = function (file, name) { |
|
206 | file.ngfName = name; |
|
207 | return file; |
|
208 | }; |
|
209 | ||
210 | this.jsonBlob = function (val) { |
|
211 | if (val != null && !angular.isString(val)) { |
|
212 | val = JSON.stringify(val); |
|
213 | } |
|
214 | var blob = new window.Blob([val], {type: 'application/json'}); |
|
215 | blob._ngfBlob = true; |
|
216 | return blob; |
|
217 | }; |
|
218 | ||
219 | this.json = function (val) { |
|
220 | return angular.toJson(val); |
|
221 | }; |
|
222 | ||
223 | function copy(obj) { |
|
224 | var clone = {}; |
|
225 | for (var key in obj) { |
|
226 | if (obj.hasOwnProperty(key)) { |
|
227 | clone[key] = obj[key]; |
|
228 | } |
|
229 | } |
|
230 | return clone; |
|
231 | } |
|
232 | ||
233 | this.isFile = function (file) { |
|
234 | return file != null && (file instanceof window.Blob || (file.flashId && file.name && file.size)); |
|
235 | }; |
|
236 | ||
237 | this.upload = function (config, internal) { |
|
238 | function toResumeFile(file, formData) { |
|
239 | if (file._ngfBlob) return file; |
|
240 | config._file = config._file || file; |
|
241 | if (config._start != null && resumeSupported) { |
|
242 | if (config._end && config._end >= file.size) { |
|
243 | config._finished = true; |
|
244 | config._end = file.size; |
|
245 | } |
|
246 | var slice = file.slice(config._start, config._end || file.size); |
|
247 | slice.name = file.name; |
|
248 | slice.ngfName = file.ngfName; |
|
249 | if (config._chunkSize) { |
|
250 | formData.append('_chunkSize', config._chunkSize); |
|
251 | formData.append('_currentChunkSize', config._end - config._start); |
|
252 | formData.append('_chunkNumber', Math.floor(config._start / config._chunkSize)); |
|
253 | formData.append('_totalSize', config._file.size); |
|
254 | } |
|
255 | return slice; |
|
256 | } |
|
257 | return file; |
|
258 | } |
|
259 | ||
260 | function addFieldToFormData(formData, val, key) { |
|
261 | if (val !== undefined) { |
|
262 | if (angular.isDate(val)) { |
|
263 | val = val.toISOString(); |
|
264 | } |
|
265 | if (angular.isString(val)) { |
|
266 | formData.append(key, val); |
|
267 | } else if (upload.isFile(val)) { |
|
268 | var file = toResumeFile(val, formData); |
|
269 | var split = key.split(','); |
|
270 | if (split[1]) { |
|
271 | file.ngfName = split[1].replace(/^\s+|\s+$/g, ''); |
|
272 | key = split[0]; |
|
273 | } |
|
274 | config._fileKey = config._fileKey || key; |
|
275 | formData.append(key, file, file.ngfName || file.name); |
|
276 | } else { |
|
277 | if (angular.isObject(val)) { |
|
278 | if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key; |
|
279 | ||
280 | val.$$ngfCircularDetection = true; |
|
281 | try { |
|
282 | for (var k in val) { |
|
283 | if (val.hasOwnProperty(k) && k !== '$$ngfCircularDetection') { |
|
284 | var objectKey = config.objectKey == null ? '[i]' : config.objectKey; |
|
285 | if (val.length && parseInt(k) > -1) { |
|
286 | objectKey = config.arrayKey == null ? objectKey : config.arrayKey; |
|
287 | } |
|
288 | addFieldToFormData(formData, val[k], key + objectKey.replace(/[ik]/g, k)); |
|
289 | } |
|
290 | } |
|
291 | } finally { |
|
292 | delete val.$$ngfCircularDetection; |
|
293 | } |
|
294 | } else { |
|
295 | formData.append(key, val); |
|
296 | } |
|
297 | } |
|
298 | } |
|
299 | } |
|
300 | ||
301 | function digestConfig() { |
|
302 | config._chunkSize = upload.translateScalars(config.resumeChunkSize); |
|
303 | config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null; |
|
304 | ||
305 | config.headers = config.headers || {}; |
|
306 | config.headers['Content-Type'] = undefined; |
|
307 | config.transformRequest = config.transformRequest ? |
|
308 | (angular.isArray(config.transformRequest) ? |
|
309 | config.transformRequest : [config.transformRequest]) : []; |
|
310 | config.transformRequest.push(function (data) { |
|
311 | var formData = new window.FormData(), key; |
|
312 | data = data || config.fields || {}; |
|
313 | if (config.file) { |
|
314 | data.file = config.file; |
|
315 | } |
|
316 | for (key in data) { |
|
317 | if (data.hasOwnProperty(key)) { |
|
318 | var val = data[key]; |
|
319 | if (config.formDataAppender) { |
|
320 | config.formDataAppender(formData, key, val); |
|
321 | } else { |
|
322 | addFieldToFormData(formData, val, key); |
|
323 | } |
|
324 | } |
|
325 | } |
|
326 | ||
327 | return formData; |
|
328 | }); |
|
329 | } |
|
330 | ||
331 | if (!internal) config = copy(config); |
|
332 | if (!config._isDigested) { |
|
333 | config._isDigested = true; |
|
334 | digestConfig(); |
|
335 | } |
|
336 | ||
337 | return sendHttp(config); |
|
338 | }; |
|
339 | ||
340 | this.http = function (config) { |
|
341 | config = copy(config); |
|
342 | config.transformRequest = config.transformRequest || function (data) { |
|
343 | if ((window.ArrayBuffer && data instanceof window.ArrayBuffer) || data instanceof window.Blob) { |
|
344 | return data; |
|
345 | } |
|
346 | return $http.defaults.transformRequest[0].apply(this, arguments); |
|
347 | }; |
|
348 | config._chunkSize = upload.translateScalars(config.resumeChunkSize); |
|
349 | config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null; |
|
350 | ||
351 | return sendHttp(config); |
|
352 | }; |
|
353 | ||
354 | this.translateScalars = function (str) { |
|
355 | if (angular.isString(str)) { |
|
356 | if (str.search(/kb/i) === str.length - 2) { |
|
357 | return parseFloat(str.substring(0, str.length - 2) * 1024); |
|
358 | } else if (str.search(/mb/i) === str.length - 2) { |
|
359 | return parseFloat(str.substring(0, str.length - 2) * 1048576); |
|
360 | } else if (str.search(/gb/i) === str.length - 2) { |
|
361 | return parseFloat(str.substring(0, str.length - 2) * 1073741824); |
|
362 | } else if (str.search(/b/i) === str.length - 1) { |
|
363 | return parseFloat(str.substring(0, str.length - 1)); |
|
364 | } else if (str.search(/s/i) === str.length - 1) { |
|
365 | return parseFloat(str.substring(0, str.length - 1)); |
|
366 | } else if (str.search(/m/i) === str.length - 1) { |
|
367 | return parseFloat(str.substring(0, str.length - 1) * 60); |
|
368 | } else if (str.search(/h/i) === str.length - 1) { |
|
369 | return parseFloat(str.substring(0, str.length - 1) * 3600); |
|
370 | } |
|
371 | } |
|
372 | return str; |
|
373 | }; |
|
374 | ||
375 | this.urlToBlob = function(url) { |
|
376 | var defer = $q.defer(); |
|
377 | $http({url: url, method: 'get', responseType: 'arraybuffer'}).then(function (resp) { |
|
378 | var arrayBufferView = new Uint8Array(resp.data); |
|
379 | var type = resp.headers('content-type') || 'image/WebP'; |
|
380 | var blob = new window.Blob([arrayBufferView], {type: type}); |
|
381 | var matches = url.match(/.*\/(.+?)(\?.*)?$/); |
|
382 | if (matches.length > 1) { |
|
383 | blob.name = matches[1]; |
|
384 | } |
|
385 | defer.resolve(blob); |
|
386 | }, function (e) { |
|
387 | defer.reject(e); |
|
388 | }); |
|
389 | return defer.promise; |
|
390 | }; |
|
391 | ||
392 | this.setDefaults = function (defaults) { |
|
393 | this.defaults = defaults || {}; |
|
394 | }; |
|
395 | ||
396 | this.defaults = {}; |
|
397 | this.version = ngFileUpload.version; |
|
398 | } |
|
399 | ||
400 | ]); |
|
401 |
@@ 28-398 (lines=371) @@ | ||
25 | ||
26 | ngFileUpload.version = '<%= pkg.version %>'; |
|
27 | ||
28 | ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) { |
|
29 | var upload = this; |
|
30 | upload.promisesCount = 0; |
|
31 | ||
32 | this.isResumeSupported = function () { |
|
33 | return window.Blob && window.Blob.prototype.slice; |
|
34 | }; |
|
35 | ||
36 | var resumeSupported = this.isResumeSupported(); |
|
37 | ||
38 | function sendHttp(config) { |
|
39 | config.method = config.method || 'POST'; |
|
40 | config.headers = config.headers || {}; |
|
41 | ||
42 | var deferred = config._deferred = config._deferred || $q.defer(); |
|
43 | var promise = deferred.promise; |
|
44 | ||
45 | function notifyProgress(e) { |
|
46 | if (deferred.notify) { |
|
47 | deferred.notify(e); |
|
48 | } |
|
49 | if (promise.progressFunc) { |
|
50 | $timeout(function () { |
|
51 | promise.progressFunc(e); |
|
52 | }); |
|
53 | } |
|
54 | } |
|
55 | ||
56 | function getNotifyEvent(n) { |
|
57 | if (config._start != null && resumeSupported) { |
|
58 | return { |
|
59 | loaded: n.loaded + config._start, |
|
60 | total: (config._file && config._file.size) || n.total, |
|
61 | type: n.type, config: config, |
|
62 | lengthComputable: true, target: n.target |
|
63 | }; |
|
64 | } else { |
|
65 | return n; |
|
66 | } |
|
67 | } |
|
68 | ||
69 | if (!config.disableProgress) { |
|
70 | config.headers.__setXHR_ = function () { |
|
71 | return function (xhr) { |
|
72 | if (!xhr || !xhr.upload || !xhr.upload.addEventListener) return; |
|
73 | config.__XHR = xhr; |
|
74 | if (config.xhrFn) config.xhrFn(xhr); |
|
75 | xhr.upload.addEventListener('progress', function (e) { |
|
76 | e.config = config; |
|
77 | notifyProgress(getNotifyEvent(e)); |
|
78 | }, false); |
|
79 | //fix for firefox not firing upload progress end, also IE8-9 |
|
80 | xhr.upload.addEventListener('load', function (e) { |
|
81 | if (e.lengthComputable) { |
|
82 | e.config = config; |
|
83 | notifyProgress(getNotifyEvent(e)); |
|
84 | } |
|
85 | }, false); |
|
86 | }; |
|
87 | }; |
|
88 | } |
|
89 | ||
90 | function uploadWithAngular() { |
|
91 | $http(config).then(function (r) { |
|
92 | if (resumeSupported && config._chunkSize && !config._finished && config._file) { |
|
93 | var fileSize = config._file && config._file.size || 0; |
|
94 | notifyProgress({ |
|
95 | loaded: Math.min(config._end, fileSize), |
|
96 | total: fileSize, |
|
97 | config: config, |
|
98 | type: 'progress' |
|
99 | } |
|
100 | ); |
|
101 | upload.upload(config, true); |
|
102 | } else { |
|
103 | if (config._finished) delete config._finished; |
|
104 | deferred.resolve(r); |
|
105 | } |
|
106 | }, function (e) { |
|
107 | deferred.reject(e); |
|
108 | }, function (n) { |
|
109 | deferred.notify(n); |
|
110 | } |
|
111 | ); |
|
112 | } |
|
113 | ||
114 | if (!resumeSupported) { |
|
115 | uploadWithAngular(); |
|
116 | } else if (config._chunkSize && config._end && !config._finished) { |
|
117 | config._start = config._end; |
|
118 | config._end += config._chunkSize; |
|
119 | uploadWithAngular(); |
|
120 | } else if (config.resumeSizeUrl) { |
|
121 | $http.get(config.resumeSizeUrl).then(function (resp) { |
|
122 | if (config.resumeSizeResponseReader) { |
|
123 | config._start = config.resumeSizeResponseReader(resp.data); |
|
124 | } else { |
|
125 | config._start = parseInt((resp.data.size == null ? resp.data : resp.data.size).toString()); |
|
126 | } |
|
127 | if (config._chunkSize) { |
|
128 | config._end = config._start + config._chunkSize; |
|
129 | } |
|
130 | uploadWithAngular(); |
|
131 | }, function (e) { |
|
132 | throw e; |
|
133 | }); |
|
134 | } else if (config.resumeSize) { |
|
135 | config.resumeSize().then(function (size) { |
|
136 | config._start = size; |
|
137 | if (config._chunkSize) { |
|
138 | config._end = config._start + config._chunkSize; |
|
139 | } |
|
140 | uploadWithAngular(); |
|
141 | }, function (e) { |
|
142 | throw e; |
|
143 | }); |
|
144 | } else { |
|
145 | if (config._chunkSize) { |
|
146 | config._start = 0; |
|
147 | config._end = config._start + config._chunkSize; |
|
148 | } |
|
149 | uploadWithAngular(); |
|
150 | } |
|
151 | ||
152 | ||
153 | promise.success = function (fn) { |
|
154 | promise.then(function (response) { |
|
155 | fn(response.data, response.status, response.headers, config); |
|
156 | }); |
|
157 | return promise; |
|
158 | }; |
|
159 | ||
160 | promise.error = function (fn) { |
|
161 | promise.then(null, function (response) { |
|
162 | fn(response.data, response.status, response.headers, config); |
|
163 | }); |
|
164 | return promise; |
|
165 | }; |
|
166 | ||
167 | promise.progress = function (fn) { |
|
168 | promise.progressFunc = fn; |
|
169 | promise.then(null, null, function (n) { |
|
170 | fn(n); |
|
171 | }); |
|
172 | return promise; |
|
173 | }; |
|
174 | promise.abort = promise.pause = function () { |
|
175 | if (config.__XHR) { |
|
176 | $timeout(function () { |
|
177 | config.__XHR.abort(); |
|
178 | }); |
|
179 | } |
|
180 | return promise; |
|
181 | }; |
|
182 | promise.xhr = function (fn) { |
|
183 | config.xhrFn = (function (origXhrFn) { |
|
184 | return function () { |
|
185 | if (origXhrFn) origXhrFn.apply(promise, arguments); |
|
186 | fn.apply(promise, arguments); |
|
187 | }; |
|
188 | })(config.xhrFn); |
|
189 | return promise; |
|
190 | }; |
|
191 | ||
192 | upload.promisesCount++; |
|
193 | if (promise['finally'] && promise['finally'] instanceof Function) { |
|
194 | promise['finally'](function () { |
|
195 | upload.promisesCount--; |
|
196 | }); |
|
197 | } |
|
198 | return promise; |
|
199 | } |
|
200 | ||
201 | this.isUploadInProgress = function () { |
|
202 | return upload.promisesCount > 0; |
|
203 | }; |
|
204 | ||
205 | this.rename = function (file, name) { |
|
206 | file.ngfName = name; |
|
207 | return file; |
|
208 | }; |
|
209 | ||
210 | this.jsonBlob = function (val) { |
|
211 | if (val != null && !angular.isString(val)) { |
|
212 | val = JSON.stringify(val); |
|
213 | } |
|
214 | var blob = new window.Blob([val], {type: 'application/json'}); |
|
215 | blob._ngfBlob = true; |
|
216 | return blob; |
|
217 | }; |
|
218 | ||
219 | this.json = function (val) { |
|
220 | return angular.toJson(val); |
|
221 | }; |
|
222 | ||
223 | function copy(obj) { |
|
224 | var clone = {}; |
|
225 | for (var key in obj) { |
|
226 | if (obj.hasOwnProperty(key)) { |
|
227 | clone[key] = obj[key]; |
|
228 | } |
|
229 | } |
|
230 | return clone; |
|
231 | } |
|
232 | ||
233 | this.isFile = function (file) { |
|
234 | return file != null && (file instanceof window.Blob || (file.flashId && file.name && file.size)); |
|
235 | }; |
|
236 | ||
237 | this.upload = function (config, internal) { |
|
238 | function toResumeFile(file, formData) { |
|
239 | if (file._ngfBlob) return file; |
|
240 | config._file = config._file || file; |
|
241 | if (config._start != null && resumeSupported) { |
|
242 | if (config._end && config._end >= file.size) { |
|
243 | config._finished = true; |
|
244 | config._end = file.size; |
|
245 | } |
|
246 | var slice = file.slice(config._start, config._end || file.size); |
|
247 | slice.name = file.name; |
|
248 | slice.ngfName = file.ngfName; |
|
249 | if (config._chunkSize) { |
|
250 | formData.append('_chunkSize', config._chunkSize); |
|
251 | formData.append('_currentChunkSize', config._end - config._start); |
|
252 | formData.append('_chunkNumber', Math.floor(config._start / config._chunkSize)); |
|
253 | formData.append('_totalSize', config._file.size); |
|
254 | } |
|
255 | return slice; |
|
256 | } |
|
257 | return file; |
|
258 | } |
|
259 | ||
260 | function addFieldToFormData(formData, val, key) { |
|
261 | if (val !== undefined) { |
|
262 | if (angular.isDate(val)) { |
|
263 | val = val.toISOString(); |
|
264 | } |
|
265 | if (angular.isString(val)) { |
|
266 | formData.append(key, val); |
|
267 | } else if (upload.isFile(val)) { |
|
268 | var file = toResumeFile(val, formData); |
|
269 | var split = key.split(','); |
|
270 | if (split[1]) { |
|
271 | file.ngfName = split[1].replace(/^\s+|\s+$/g, ''); |
|
272 | key = split[0]; |
|
273 | } |
|
274 | config._fileKey = config._fileKey || key; |
|
275 | formData.append(key, file, file.ngfName || file.name); |
|
276 | } else { |
|
277 | if (angular.isObject(val)) { |
|
278 | if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key; |
|
279 | ||
280 | val.$$ngfCircularDetection = true; |
|
281 | try { |
|
282 | for (var k in val) { |
|
283 | if (val.hasOwnProperty(k) && k !== '$$ngfCircularDetection') { |
|
284 | var objectKey = config.objectKey == null ? '[i]' : config.objectKey; |
|
285 | if (val.length && parseInt(k) > -1) { |
|
286 | objectKey = config.arrayKey == null ? objectKey : config.arrayKey; |
|
287 | } |
|
288 | addFieldToFormData(formData, val[k], key + objectKey.replace(/[ik]/g, k)); |
|
289 | } |
|
290 | } |
|
291 | } finally { |
|
292 | delete val.$$ngfCircularDetection; |
|
293 | } |
|
294 | } else { |
|
295 | formData.append(key, val); |
|
296 | } |
|
297 | } |
|
298 | } |
|
299 | } |
|
300 | ||
301 | function digestConfig() { |
|
302 | config._chunkSize = upload.translateScalars(config.resumeChunkSize); |
|
303 | config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null; |
|
304 | ||
305 | config.headers = config.headers || {}; |
|
306 | config.headers['Content-Type'] = undefined; |
|
307 | config.transformRequest = config.transformRequest ? |
|
308 | (angular.isArray(config.transformRequest) ? |
|
309 | config.transformRequest : [config.transformRequest]) : []; |
|
310 | config.transformRequest.push(function (data) { |
|
311 | var formData = new window.FormData(), key; |
|
312 | data = data || config.fields || {}; |
|
313 | if (config.file) { |
|
314 | data.file = config.file; |
|
315 | } |
|
316 | for (key in data) { |
|
317 | if (data.hasOwnProperty(key)) { |
|
318 | var val = data[key]; |
|
319 | if (config.formDataAppender) { |
|
320 | config.formDataAppender(formData, key, val); |
|
321 | } else { |
|
322 | addFieldToFormData(formData, val, key); |
|
323 | } |
|
324 | } |
|
325 | } |
|
326 | ||
327 | return formData; |
|
328 | }); |
|
329 | } |
|
330 | ||
331 | if (!internal) config = copy(config); |
|
332 | if (!config._isDigested) { |
|
333 | config._isDigested = true; |
|
334 | digestConfig(); |
|
335 | } |
|
336 | ||
337 | return sendHttp(config); |
|
338 | }; |
|
339 | ||
340 | this.http = function (config) { |
|
341 | config = copy(config); |
|
342 | config.transformRequest = config.transformRequest || function (data) { |
|
343 | if ((window.ArrayBuffer && data instanceof window.ArrayBuffer) || data instanceof window.Blob) { |
|
344 | return data; |
|
345 | } |
|
346 | return $http.defaults.transformRequest[0].apply(this, arguments); |
|
347 | }; |
|
348 | config._chunkSize = upload.translateScalars(config.resumeChunkSize); |
|
349 | config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null; |
|
350 | ||
351 | return sendHttp(config); |
|
352 | }; |
|
353 | ||
354 | this.translateScalars = function (str) { |
|
355 | if (angular.isString(str)) { |
|
356 | if (str.search(/kb/i) === str.length - 2) { |
|
357 | return parseFloat(str.substring(0, str.length - 2) * 1024); |
|
358 | } else if (str.search(/mb/i) === str.length - 2) { |
|
359 | return parseFloat(str.substring(0, str.length - 2) * 1048576); |
|
360 | } else if (str.search(/gb/i) === str.length - 2) { |
|
361 | return parseFloat(str.substring(0, str.length - 2) * 1073741824); |
|
362 | } else if (str.search(/b/i) === str.length - 1) { |
|
363 | return parseFloat(str.substring(0, str.length - 1)); |
|
364 | } else if (str.search(/s/i) === str.length - 1) { |
|
365 | return parseFloat(str.substring(0, str.length - 1)); |
|
366 | } else if (str.search(/m/i) === str.length - 1) { |
|
367 | return parseFloat(str.substring(0, str.length - 1) * 60); |
|
368 | } else if (str.search(/h/i) === str.length - 1) { |
|
369 | return parseFloat(str.substring(0, str.length - 1) * 3600); |
|
370 | } |
|
371 | } |
|
372 | return str; |
|
373 | }; |
|
374 | ||
375 | this.urlToBlob = function(url) { |
|
376 | var defer = $q.defer(); |
|
377 | $http({url: url, method: 'get', responseType: 'arraybuffer'}).then(function (resp) { |
|
378 | var arrayBufferView = new Uint8Array(resp.data); |
|
379 | var type = resp.headers('content-type') || 'image/WebP'; |
|
380 | var blob = new window.Blob([arrayBufferView], {type: type}); |
|
381 | var matches = url.match(/.*\/(.+?)(\?.*)?$/); |
|
382 | if (matches.length > 1) { |
|
383 | blob.name = matches[1]; |
|
384 | } |
|
385 | defer.resolve(blob); |
|
386 | }, function (e) { |
|
387 | defer.reject(e); |
|
388 | }); |
|
389 | return defer.promise; |
|
390 | }; |
|
391 | ||
392 | this.setDefaults = function (defaults) { |
|
393 | this.defaults = defaults || {}; |
|
394 | }; |
|
395 | ||
396 | this.defaults = {}; |
|
397 | this.version = ngFileUpload.version; |
|
398 | } |
|
399 | ||
400 | ]); |
|
401 |