/*! * Name: vue-upload-component * Version: 2.6.2 * Author: LianYue */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.VueUploadComponent = factory()); }(this, (function () { 'use strict'; (function () { if (typeof document !== 'undefined') { var head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'), css = "";style.type = 'text/css';if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); }head.appendChild(style); } })(); var InputFile = { render: function render() { var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('input', { attrs: { "type": "file", "name": _vm.$parent.name, "id": _vm.$parent.inputId || _vm.$parent.name, "accept": _vm.$parent.accept, "webkitdirectory": _vm.$parent.directory && _vm.$parent.features.directory, "directory": _vm.$parent.directory && _vm.$parent.features.directory, "multiple": _vm.$parent.multiple && _vm.$parent.features.html5 }, on: { "change": _vm.change } }); }, staticRenderFns: [], methods: { change: function change(e) { this.$destroy(); this.$parent.addInputFile(e.target); // eslint-disable-next-line new this.constructor({ parent: this.$parent, el: this.$el }); } } }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } (function () { if (typeof document !== 'undefined') { var head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'), css = " .file-uploads { overflow: hidden; position: relative; text-align: center; display: inline-block; } .file-uploads.file-uploads-html4 input[type=\"file\"] { opacity: 0; font-size: 20em; z-index: 1; top: 0; left: 0; right: 0; bottom: 0; position: absolute; width: 100%; height: 100%; } .file-uploads.file-uploads-html5 input[type=\"file\"] { overflow: hidden; position: fixed; width: 1px; height: 1px; z-index: -1; opacity: 0; } ";style.type = 'text/css';if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); }head.appendChild(style); } })(); var FileUpload = { render: function render() { var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('label', { class: _vm.className }, [_vm._t("default"), _vm._v(" "), _c('input-file')], 2); }, staticRenderFns: [], components: { InputFile: InputFile }, props: { inputId: { type: String }, name: { type: String, default: 'file' }, accept: { type: String }, multiple: { type: Boolean }, addIndex: { type: [Boolean, Number] }, directory: { type: Boolean }, postAction: { type: String }, putAction: { type: String }, headers: { type: Object, default: Object }, data: { type: Object, default: Object }, timeout: { type: Number, default: 0 }, drop: { default: false }, dropDirectory: { type: Boolean, default: true }, size: { type: Number, default: 0 }, extensions: { default: Array }, value: { type: Array, default: Array }, thread: { type: Number, default: 1 } }, data: function data() { return { files: this.value, features: { html5: true, directory: false, drag: false }, active: false, dropActive: false, uploading: 0, destroy: false }; }, /** * mounted * @return {[type]} [description] */ mounted: function mounted() { var input = document.createElement('input'); input.type = 'file'; input.multiple = true; // html5 特征 if (window.FormData && input.files) { // 上传目录特征 if (typeof input.webkitdirectory === 'boolean' || typeof input.directory === 'boolean') { this.features.directory = true; } // 拖拽特征 if (this.features.html5 && typeof input.ondrop !== 'undefined') { this.features.drop = true; } } else { this.features.html5 = false; } // files 定位缓存 this.maps = {}; this.$nextTick(function () { // 更新下父级 if (this.$parent) { this.$parent.$forceUpdate(); } // 拖拽渲染 this.watchDrop(this.drop); }); }, /** * beforeDestroy * @return {[type]} [description] */ beforeDestroy: function beforeDestroy() { // 已销毁 this.destroy = true; // 设置成不激活 this.active = false; }, computed: { /** * uploading 正在上传的线程 * @return {[type]} [description] */ /** * uploaded 文件列表是否全部已上传 * @return {[type]} [description] */ uploaded: function uploaded() { var file = void 0; for (var i = 0; i < this.files.length; i++) { file = this.files[i]; if (file.fileObject && !file.error && !file.success) { return false; } } return true; }, className: function className() { return ['file-uploads', this.features.html5 ? 'file-uploads-html5' : 'file-uploads-html4', this.features.directory && this.directory ? 'file-uploads-directory' : undefined, this.features.drop && this.drop ? 'file-uploads-drop' : undefined]; } }, watch: { active: function active(_active) { this.watchActive(_active); }, dropActive: function dropActive() { if (this.$parent) { this.$parent.$forceUpdate(); } }, drop: function drop(value) { this.watchDrop(value); }, value: function value(files) { if (this.files === files) { return; } this.files = files; var oldMaps = this.maps; // 重写 maps 缓存 this.maps = {}; for (var i = 0; i < this.files.length; i++) { var file = this.files[i]; this.maps[file.id] = file; } // add, update for (var key in this.maps) { var newFile = this.maps[key]; var oldFile = oldMaps[key]; if (newFile !== oldFile) { this.emitFile(newFile, oldFile); } } // delete for (var _key in oldMaps) { if (!this.maps[_key]) { this.emitFile(undefined, oldMaps[_key]); } } } }, methods: { // 清空 clear: function clear() { if (this.files.length) { var files = this.files; this.files = []; // 定位 this.maps = {}; // 事件 this.emitInput(); for (var i = 0; i < files.length; i++) { this.emitFile(undefined, files[i]); } } return true; }, // 选择 get: function get(id) { if (!id) { return false; } if ((typeof id === 'undefined' ? 'undefined' : _typeof(id)) === 'object') { return this.maps[id.id] || false; } return this.maps[id] || false; }, // 添加 add: function add(_files) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.addIndex; var files = _files; var isArray = files instanceof Array; // 不是数组整理成数组 if (!isArray) { files = [files]; } // 遍历规范对象 var addFiles = []; for (var i = 0; i < files.length; i++) { var file = files[i]; if (this.features.html5 && file instanceof Blob) { file = { file: file, size: file.size, name: file.webkitRelativePath || file.relativePath || file.name || 'unknown', type: file.type }; } var fileObject = false; if (file.fileObject === false) { // false } else if (file.fileObject) { fileObject = true; } else if (typeof Element !== 'undefined' && file.el instanceof Element) { fileObject = true; } else if (typeof Blob !== 'undefined' && file.file instanceof Blob) { fileObject = true; } if (fileObject) { file = _extends({ fileObject: true, size: -1, name: 'Filename', type: '', active: false, error: '', success: false, putAction: this.putAction, postAction: this.postAction, timeout: this.timeout }, file, { response: {}, progress: '0.00', // 只读 speed: 0 // 只读 // xhr: false, // 只读 // iframe: false, // 只读 }); file.data = _extends({}, this.data, file.data ? file.data : {}); file.headers = _extends({}, this.headers, file.headers ? file.headers : {}); } // 必须包含 id if (!file.id) { file.id = Math.random().toString(36).substr(2); } if (this.emitFilter(file, undefined)) { continue; } addFiles.push(file); // 只允许单个文件 if (!this.multiple) { break; } } // 没有文件 if (!addFiles.length) { return false; } // 只允许单个文件 删除所有 if (!this.multiple) { this.clear(); } // 添加进去 files var newFiles = void 0; if (index === true || index === 0) { newFiles = addFiles.concat(this.files); } else if (index) { newFiles = addFiles.concat([]); newFiles.splice(index, 0, addFiles); } else { newFiles = this.files.concat(addFiles); } this.files = newFiles; // 定位 for (var _i = 0; _i < addFiles.length; _i++) { var _file2 = addFiles[_i]; this.maps[_file2.id] = _file2; } // 事件 this.emitInput(); for (var _i2 = 0; _i2 < addFiles.length; _i2++) { this.emitFile(addFiles[_i2], undefined); } return isArray ? addFiles : addFiles[0]; }, // 添加表单文件 addInputFile: function addInputFile(el) { var files = []; if (el.files) { for (var i = 0; i < el.files.length; i++) { var file = el.files[i]; files.push({ size: file.size, name: file.webkitRelativePath || file.relativePath || file.name, type: file.type, file: file, el: el }); } } else { files.push({ name: el.value.replace(/^.*?([^\/\\\r\n]+)$/, '$1'), el: el }); } return this.add(files); }, // 添加 DataTransfer addDataTransfer: function addDataTransfer(dataTransfer) { var _this = this; var files = []; if (dataTransfer.items && dataTransfer.items.length) { var items = []; for (var i = 0; i < dataTransfer.items.length; i++) { var item = dataTransfer.items[i]; if (item.getAsEntry) { item = item.getAsEntry(); } else if (item.webkitGetAsEntry) { item = item.webkitGetAsEntry(); } else { item = item.getAsFile(); } if (item) { items.push(item); } } return new Promise(function (resolve, reject) { var forEach = function forEach(i) { var item = items[i]; // 结束 或者已有文件了 if (!item || !_this.multiple && files.length) { return resolve(_this.add(files)); } _this.getEntry(item).then(function (results) { files.push.apply(files, _toConsumableArray(results)); forEach(i + 1); }); }; forEach(0); }); } if (dataTransfer.files.length) { for (var _i3 = 0; _i3 < dataTransfer.files.length; _i3++) { files.push(dataTransfer.files[_i3]); if (!this.multiple) { break; } } return Promise.resolve(this.add(files)); } return Promise.resolve([]); }, // 获得 entry getEntry: function getEntry(entry) { var _this2 = this; var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; return new Promise(function (resolve, reject) { if (entry.isFile) { entry.file(function (file) { resolve([{ size: file.size, name: path + file.name, type: file.type, file: file }]); }); } else if (entry.isDirectory && _this2.dropDirectory) { entry.createReader().readEntries(function (entries) { var files = []; var forEach = function forEach(i) { if (!entries[i] || files.length && !_this2.multiple) { return resolve(files); } _this2.getEntry(entries[i], path + entry.name + '/').then(function (results) { files.push.apply(files, _toConsumableArray(results)); forEach(i + 1); }); }; forEach(0); }); } else { resolve([]); } }); }, replace: function replace(id1, id2) { var file1 = this.get(id1); var file2 = this.get(id2); if (!file1 || !file2 || file1 === file2) { return false; } var files = this.files.concat([]); var index1 = files.indexOf(file1); var index2 = files.indexOf(file2); if (index1 === -1 || index2 === -1) { return false; } files[index1] = file2; files[index2] = file1; this.files = files; this.emitInput(); return true; }, // 移除 remove: function remove(id) { var file = this.get(id); if (file) { if (this.emitFilter(undefined, file)) { return false; } var files = this.files.concat([]); var index = files.indexOf(file); if (index === -1) { console.error('remove', file); return false; } files.splice(index, 1); this.files = files; // 定位 delete this.maps[file.id]; // 事件 this.emitInput(); this.emitFile(undefined, file); } return file; }, // 更新 update: function update(id, data) { var file = this.get(id); if (file) { var newFile = _extends({}, file, data); // 停用必须加上错误 if (file.fileObject && file.active && !newFile.active && !newFile.error && !newFile.success) { newFile.error = 'abort'; } if (this.emitFilter(newFile, file)) { return false; } var files = this.files.concat([]); var index = files.indexOf(file); if (index === -1) { console.error('update', file); return false; } files.splice(index, 1, newFile); this.files = files; // 删除 旧定位 写入 新定位 (已便支持修改id) delete this.maps[file.id]; this.maps[newFile.id] = newFile; // 事件 this.emitInput(); this.emitFile(newFile, file); return newFile; } return false; }, // 预处理 事件 过滤器 emitFilter: function emitFilter(newFile, oldFile) { var isPrevent = false; this.$emit('input-filter', newFile, oldFile, function () { isPrevent = true; return isPrevent; }); return isPrevent; }, // 处理后 事件 分发 emitFile: function emitFile(newFile, oldFile) { this.$emit('input-file', newFile, oldFile); if (newFile && newFile.fileObject && newFile.active && (!oldFile || !oldFile.active)) { this.uploading++; // 激活 this.$nextTick(function () { var _this3 = this; setTimeout(function () { _this3.upload(newFile).then(function () { // eslint-disable-next-line newFile = _this3.get(newFile); if (newFile && newFile.fileObject) { _this3.update(newFile, { active: false, success: !newFile.error }); } }).catch(function (e) { _this3.update(newFile, { active: false, success: false, error: e.code || e.error || e.message || e }); }); }, parseInt(Math.random() * 50 + 50, 10)); }); } else if ((!newFile || !newFile.fileObject || !newFile.active) && oldFile && oldFile.fileObject && oldFile.active) { // 停止 this.uploading--; } // 自动延续激活 if (this.active && (Boolean(newFile) !== Boolean(oldFile) || newFile.active !== oldFile.active)) { this.watchActive(true); } }, emitInput: function emitInput() { this.$emit('input', this.files); }, // 上传 upload: function upload(id) { var file = this.get(id); // 被删除 if (!file) { return Promise.reject('not_exists'); } // 不是文件对象 if (!file.fileObject) { return Promise.reject('file_object'); } // 有错误直接响应 if (file.error) { return Promise.reject(file.error); } // 已完成直接响应 if (file.success) { return Promise.resolve(file); } // 后缀 var extensions = this.extensions; if (extensions && (extensions.length || typeof extensions.length === 'undefined')) { if ((typeof extensions === 'undefined' ? 'undefined' : _typeof(extensions)) !== 'object' || !(extensions instanceof RegExp)) { if (typeof extensions === 'string') { extensions = extensions.split(',').map(function (value) { return value.trim(); }).filter(function (value) { return value; }); } extensions = new RegExp('\\.(' + extensions.join('|').replace(/\./g, '\\.') + ')$', 'i'); } if (file.name.search(extensions) === -1) { return Promise.reject('extension'); } } // 大小 if (this.size > 0 && file.size >= 0 && file.size > this.size) { return Promise.reject('size'); } if (this.features.html5 && file.putAction) { return this.uploadPut(file); } else if (this.features.html5) { return this.uploadHtml5(file); } else { return this.uploadHtml4(file); } }, uploadPut: function uploadPut(file) { var querys = []; var value = void 0; for (var key in file.data) { value = file.data[key]; if (value !== null && value !== undefined) { querys.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); } } var queryString = querys.length ? (file.putAction.indexOf('?') === -1 ? '?' : '&') + querys.join('&') : ''; var xhr = new XMLHttpRequest(); xhr.open('PUT', file.putAction + queryString); return this.uploadXhr(xhr, file, file.file); }, uploadHtml5: function uploadHtml5(file) { var form = new window.FormData(); var value = void 0; for (var key in file.data) { value = file.data[key]; if (value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && typeof value.toString !== 'function') { form.append(key, JSON.stringify(value)); } else if (value !== null && value !== undefined) { form.append(key, value); } } form.append(this.name, file.file, file.file.filename || file.name); var xhr = new XMLHttpRequest(); xhr.open('POST', file.postAction); return this.uploadXhr(xhr, file, form); }, uploadXhr: function uploadXhr(xhr, _file, body) { var _this4 = this; var file = _file; var speedTime = 0; var speedLoaded = 0; // 进度条 xhr.upload.onprogress = function (e) { // 还未开始上传 已删除 未激活 file = _this4.get(file); if (!e.lengthComputable || !file || !file.fileObject || !file.active) { return; } // 进度 速度 每秒更新一次 var speedTime2 = Math.round(Date.now() / 1000); if (speedTime2 === speedTime) { return; } speedTime = speedTime2; file = _this4.update(file, { progress: (e.loaded / e.total * 100).toFixed(2), speed: e.loaded - speedLoaded }); speedLoaded = e.loaded; }; // 检查激活状态 var interval = setInterval(function () { file = _this4.get(file); if (file && file.fileObject && !file.success && !file.error && file.active) { return; } if (interval) { clearInterval(interval); interval = false; } try { xhr.abort(); xhr.timeout = 1; } catch (e) {} }, 100); return new Promise(function (resolve, reject) { var complete = void 0; var fn = function fn(e) { // 已经处理过了 if (complete) { return; } complete = true; if (interval) { clearInterval(interval); interval = false; } file = _this4.get(file); // 不存在直接响应 if (!file) { return reject('not_exists'); } // 不是文件对象 if (!file.fileObject) { return reject('file_object'); } // 有错误自动响应 if (file.error) { return reject(file.error); } // 未激活 if (!file.active) { return reject('abort'); } // 已完成 直接相应 if (file.success) { return resolve(file); } var data = {}; switch (e.type) { case 'timeout': case 'abort': data.error = e.type; break; case 'error': if (!xhr.status) { data.error = 'network'; } else if (xhr.status >= 500) { data.error = 'server'; } else if (xhr.status >= 400) { data.error = 'denied'; } break; default: if (xhr.status >= 500) { data.error = 'server'; } else if (xhr.status >= 400) { data.error = 'denied'; } else { data.progress = '100.00'; } } if (xhr.responseText) { var contentType = xhr.getResponseHeader('Content-Type'); if (contentType && contentType.indexOf('/json') !== -1) { data.response = JSON.parse(xhr.responseText); } else { data.response = xhr.responseText; } } // 更新 file = _this4.update(file, data); // 相应错误 if (file.error) { return reject(file.error); } // 响应 return resolve(file); }; // 事件 xhr.onload = fn; xhr.onerror = fn; xhr.onabort = fn; xhr.ontimeout = fn; // 超时 if (file.timeout) { xhr.timeout = file.timeout; } // headers for (var key in file.headers) { xhr.setRequestHeader(key, file.headers[key]); } // 更新 xhr file = _this4.update(file, { xhr: xhr }); // 开始上传 xhr.send(body); }); }, uploadHtml4: function uploadHtml4(_file) { var _this5 = this; var file = _file; var onKeydown = function onKeydown(e) { if (e.keyCode === 27) { e.preventDefault(); } }; var iframe = document.createElement('iframe'); iframe.id = 'upload-iframe-' + file.id; iframe.name = 'upload-iframe-' + file.id; iframe.src = 'about:blank'; iframe.setAttribute('style', 'width:1px;height:1px;top:-999em;position:absolute; margin-top:-999em;'); var form = document.createElement('form'); form.action = file.postAction; form.name = 'upload-form-' + file.id; form.setAttribute('method', 'POST'); form.setAttribute('target', 'upload-iframe-' + file.id); form.setAttribute('enctype', 'multipart/form-data'); var value = void 0; var input = void 0; for (var key in file.data) { value = file.data[key]; if (value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && typeof value.toString !== 'function') { value = JSON.stringify(value); } if (value !== null && value !== undefined) { input = document.createElement('input'); input.type = 'hidden'; input.name = key; form.appendChild(input); } } form.appendChild(file.el); document.body.appendChild(iframe).appendChild(form); var getResponseData = function getResponseData() { var doc = void 0; try { if (iframe.contentWindow) { doc = iframe.contentWindow.document; } } catch (err) {} if (!doc) { try { doc = iframe.contentDocument ? iframe.contentDocument : iframe.document; } catch (err) { doc = iframe.document; } } if (doc && doc.body) { return doc.body.innerHTML; } return null; }; return new Promise(function (resolve, reject) { setTimeout(function () { file = _this5.update(file, { iframe: iframe }); // 不存在 if (!file) { return reject('not_exists'); } // 定时检查 var interval = setInterval(function () { file = _this5.get(file); if (file && file.fileObject && !file.success && !file.error && file.active) { return; } if (interval) { clearInterval(interval); interval = false; } iframe.onabort({ type: file ? 'abort' : 'not_exists' }); }, 100); var complete = void 0; var fn = function fn(e) { // 已经处理过了 if (complete) { return; } complete = true; if (interval) { clearInterval(interval); interval = false; } // 关闭 esc 事件 document.body.removeEventListener('keydown', onKeydown); file = _this5.get(file); // 不存在直接响应 if (!file) { return reject('not_exists'); } // 不是文件对象 if (!file.fileObject) { return reject('file_object'); } // 有错误自动响应 if (file.error) { return reject(file.error); } // 未激活 if (!file.active) { return reject('abort'); } // 已完成 直接相应 if (file.success) { return resolve(file); } var response = getResponseData(); var data = {}; switch (e.type) { case 'abort': data.error = 'abort'; break; case 'error': if (file.error) { data.error = file.error; } else if (response === null) { data.error = 'network'; } else { data.error = 'denied'; } break; default: if (file.error) { data.error = file.error; } else if (data === null) { data.error = 'network'; } else { data.progress = '100.00'; } } if (response !== null) { if (response && response.substr(0, 1) === '{' && response.substr(response.length - 1, 1) === '}') { try { response = JSON.parse(response); } catch (err) {} } data.response = response; } // 更新 file = _this5.update(file, data); if (file.error) { return reject(file.error); } // 响应 return resolve(file); }; // 添加事件 iframe.onload = fn; iframe.onerror = fn; iframe.onabort = fn; // 禁止 esc 键 document.body.addEventListener('keydown', onKeydown); // 提交 form.submit(); }, 50); }).then(function (res) { iframe.parentNode && iframe.parentNode.removeChild(iframe); return res; }).catch(function (res) { iframe.parentNode && iframe.parentNode.removeChild(iframe); return res; }); }, watchActive: function watchActive(active) { var file = void 0; var index = 0; while (file = this.files[index]) { index++; if (!file.fileObject) { // 不是文件对象 } else if (active && !this.destroy) { if (this.uploading >= this.thread || this.uploading && !this.features.html5) { break; } if (!file.active && !file.error && !file.success) { this.update(file, { active: true }); } } else { if (file.active) { this.update(file, { active: false }); } } } if (this.uploading === 0) { this.active = false; } }, watchDrop: function watchDrop(_el) { var el = _el; if (!this.features.drop) { return; } // 移除挂载 if (this.dropElement) { try { document.removeEventListener('dragenter', this.onDragenter, false); document.removeEventListener('dragleave', this.onDragleave, false); this.dropElement.removeEventListener('dragover', this.onDragover, false); this.dropElement.removeEventListener('drop', this.onDrop, false); } catch (e) {} } if (!el) { el = false; } else if (typeof el === 'string') { el = document.querySelector(el) || this.$root.$el.querySelector(el); } else if (el === true) { el = this.$parent.$el; } this.dropElement = el; if (this.dropElement) { document.addEventListener('dragenter', this.onDragenter, false); document.addEventListener('dragleave', this.onDragleave, false); this.dropElement.addEventListener('dragover', this.onDragover, false); this.dropElement.addEventListener('drop', this.onDrop, false); } }, onDragenter: function onDragenter(e) { e.preventDefault(); if (!this.dropActive) { this.dropActive = true; } }, onDragleave: function onDragleave(e) { e.preventDefault(); if (e.target.nodeName === 'HTML' || e.screenX === 0 && e.screenY === 0 && e.screenY === 0 && !e.fromElement && e.offsetX < 0) { this.dropActive = false; } }, onDragover: function onDragover(e) { e.preventDefault(); }, onDrop: function onDrop(e) { e.preventDefault(); this.dropActive = false; this.addDataTransfer(e.dataTransfer); } } }; var FileUpload$1 = Object.freeze({ default: FileUpload }); var require$$0 = ( FileUpload$1 && FileUpload ) || FileUpload$1; var src = require$$0; return src; }))); //# sourceMappingURL=vue-upload-component.js.map