You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vue-upload-component/dist/vue-upload-component.part.js

2050 lines
57 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*!
* Name: vue-upload-component
* Version: 2.8.12
* 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';
/**
* Creates a XHR request
*
* @param {Object} options
*/
var createRequest = function createRequest(options) {
var xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', options.url);
xhr.responseType = 'json';
if (options.headers) {
Object.keys(options.headers).forEach(function (key) {
xhr.setRequestHeader(key, options.headers[key]);
});
}
return xhr;
};
/**
* Sends a XHR request with certain body
*
* @param {XMLHttpRequest} xhr
* @param {Object} body
*/
var sendRequest = function sendRequest(xhr, body) {
return new Promise(function (resolve, reject) {
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
var response;
try {
response = JSON.parse(xhr.response);
} catch (err) {
response = xhr.response;
}
resolve(response);
} else {
reject(xhr.response);
}
};
xhr.onerror = function () {
return reject(xhr.response);
};
xhr.send(JSON.stringify(body));
});
};
/**
* Sends a XHR request with certain form data
*
* @param {XMLHttpRequest} xhr
* @param {Object} data
*/
var sendFormRequest = function sendFormRequest(xhr, data) {
var body = new FormData();
for (var name in data) {
body.append(name, data[name]);
}
return new Promise(function (resolve, reject) {
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
var response;
try {
response = JSON.parse(xhr.response);
} catch (err) {
response = xhr.response;
}
resolve(response);
} else {
reject(xhr.response);
}
};
xhr.onerror = function () {
return reject(xhr.response);
};
xhr.send(body);
});
};
/**
* Creates and sends XHR request
*
* @param {Object} options
*
* @returns Promise
*/
function request (options) {
var xhr = createRequest(options);
return sendRequest(xhr, options.body);
}
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ChunkUploadHandler = function () {
/**
* Constructor
*
* @param {File} file
* @param {Object} options
*/
function ChunkUploadHandler(file, options) {
_classCallCheck(this, ChunkUploadHandler);
this.file = file;
this.options = options;
}
/**
* Gets the max retries from options
*/
_createClass(ChunkUploadHandler, [{
key: 'createChunks',
/**
* Creates all the chunks in the initial state
*/
value: function createChunks() {
this.chunks = [];
var start = 0;
var end = this.chunkSize;
while (start < this.fileSize) {
this.chunks.push({
blob: this.file.file.slice(start, end),
startOffset: start,
active: false,
retries: this.maxRetries
});
start = end;
end = start + this.chunkSize;
}
}
/**
* Updates the progress of the file with the handler's progress
*/
}, {
key: 'updateFileProgress',
value: function updateFileProgress() {
this.file.progress = this.progress;
}
/**
* Paues the upload process
* - Stops all active requests
* - Sets the file not active
*/
}, {
key: 'pause',
value: function pause() {
this.file.active = false;
this.stopChunks();
}
/**
* Stops all the current chunks
*/
}, {
key: 'stopChunks',
value: function stopChunks() {
this.chunksUploading.forEach(function (chunk) {
chunk.xhr.abort();
chunk.active = false;
});
}
/**
* Resumes the file upload
* - Sets the file active
* - Starts the following chunks
*/
}, {
key: 'resume',
value: function resume() {
this.file.active = true;
this.startChunking();
}
/**
* Starts the file upload
*
* @returns Promise
* - resolve The file was uploaded
* - reject The file upload failed
*/
}, {
key: 'upload',
value: function upload() {
var _this = this;
this.promise = new Promise(function (resolve, reject) {
_this.resolve = resolve;
_this.reject = reject;
});
this.start();
return this.promise;
}
/**
* Start phase
* Sends a request to the backend to initialise the chunks
*/
}, {
key: 'start',
value: function start() {
var _this2 = this;
request({
method: 'POST',
headers: Object.assign({}, this.headers, {
'Content-Type': 'application/json'
}),
url: this.action,
body: Object.assign(this.startBody, {
phase: 'start',
mime_type: this.fileType,
size: this.fileSize,
name: this.fileName
})
}).then(function (res) {
if (res.status !== 'success') {
_this2.file.response = res;
return _this2.reject('server');
}
_this2.sessionId = res.data.session_id;
_this2.chunkSize = res.data.end_offset;
_this2.createChunks();
_this2.startChunking();
}).catch(function (res) {
_this2.file.response = res;
_this2.reject('server');
});
}
/**
* Starts to upload chunks
*/
}, {
key: 'startChunking',
value: function startChunking() {
for (var i = 0; i < this.maxActiveChunks; i++) {
this.uploadNextChunk();
}
}
/**
* Uploads the next chunk
* - Won't do anything if the process is paused
* - Will start finish phase if there are no more chunks to upload
*/
}, {
key: 'uploadNextChunk',
value: function uploadNextChunk() {
if (this.file.active) {
if (this.hasChunksToUpload) {
return this.uploadChunk(this.chunksToUpload[0]);
}
if (this.chunksUploading.length === 0) {
return this.finish();
}
}
}
/**
* Uploads a chunk
* - Sends the chunk to the backend
* - Sets the chunk as uploaded if everything went well
* - Decreases the number of retries if anything went wrong
* - Fails if there are no more retries
*
* @param {Object} chunk
*/
}, {
key: 'uploadChunk',
value: function uploadChunk(chunk) {
var _this3 = this;
chunk.progress = 0;
chunk.active = true;
this.updateFileProgress();
chunk.xhr = createRequest({
method: 'POST',
headers: this.headers,
url: this.action
});
chunk.xhr.upload.addEventListener('progress', function (evt) {
if (evt.lengthComputable) {
chunk.progress = Math.round(evt.loaded / evt.total * 100);
}
}, false);
sendFormRequest(chunk.xhr, Object.assign(this.uploadBody, {
phase: 'upload',
session_id: this.sessionId,
start_offset: chunk.startOffset,
chunk: chunk.blob
})).then(function (res) {
chunk.active = false;
if (res.status === 'success') {
chunk.uploaded = true;
} else {
if (chunk.retries-- <= 0) {
_this3.stopChunks();
return _this3.reject('upload');
}
}
_this3.uploadNextChunk();
}).catch(function () {
chunk.active = false;
if (chunk.retries-- <= 0) {
_this3.stopChunks();
return _this3.reject('upload');
}
_this3.uploadNextChunk();
});
}
/**
* Finish phase
* Sends a request to the backend to finish the process
*/
}, {
key: 'finish',
value: function finish() {
var _this4 = this;
this.updateFileProgress();
request({
method: 'POST',
headers: Object.assign({}, this.headers, {
'Content-Type': 'application/json'
}),
url: this.action,
body: Object.assign(this.finishBody, {
phase: 'finish',
session_id: this.sessionId
})
}).then(function (res) {
_this4.file.response = res;
if (res.status !== 'success') {
return _this4.reject('server');
}
_this4.resolve(res);
}).catch(function (res) {
_this4.file.response = res;
_this4.reject('server');
});
}
}, {
key: 'maxRetries',
get: function get() {
return parseInt(this.options.maxRetries);
}
/**
* Gets the max number of active chunks being uploaded at once from options
*/
}, {
key: 'maxActiveChunks',
get: function get() {
return parseInt(this.options.maxActive);
}
/**
* Gets the file type
*/
}, {
key: 'fileType',
get: function get() {
return this.file.type;
}
/**
* Gets the file size
*/
}, {
key: 'fileSize',
get: function get() {
return this.file.size;
}
/**
* Gets the file size
*/
}, {
key: 'fileName',
get: function get() {
return this.file.name;
}
/**
* Gets action (url) to upload the file
*/
}, {
key: 'action',
get: function get() {
return this.options.action || null;
}
/**
* Gets the body to be merged when sending the request in start phase
*/
}, {
key: 'startBody',
get: function get() {
return this.options.startBody || {};
}
/**
* Gets the body to be merged when sending the request in upload phase
*/
}, {
key: 'uploadBody',
get: function get() {
return this.options.uploadBody || {};
}
/**
* Gets the body to be merged when sending the request in finish phase
*/
}, {
key: 'finishBody',
get: function get() {
return this.options.finishBody || {};
}
/**
* Gets the headers of the requests from options
*/
}, {
key: 'headers',
get: function get() {
return this.options.headers || {};
}
/**
* Whether it's ready to upload files or not
*/
}, {
key: 'readyToUpload',
get: function get() {
return !!this.chunks;
}
/**
* Gets the progress of the chunk upload
* - Gets all the completed chunks
* - Gets the progress of all the chunks that are being uploaded
*/
}, {
key: 'progress',
get: function get() {
var _this5 = this;
var completedProgress = this.chunksUploaded.length / this.chunks.length * 100;
var uploadingProgress = this.chunksUploading.reduce(function (progress, chunk) {
return progress + (chunk.progress | 0) / _this5.chunks.length;
}, 0);
return Math.min(completedProgress + uploadingProgress, 100);
}
/**
* Gets all the chunks that are pending to be uploaded
*/
}, {
key: 'chunksToUpload',
get: function get() {
return this.chunks.filter(function (chunk) {
return !chunk.active && !chunk.uploaded;
});
}
/**
* Whether there are chunks to upload or not
*/
}, {
key: 'hasChunksToUpload',
get: function get() {
return this.chunksToUpload.length > 0;
}
/**
* Gets all the chunks that are uploading
*/
}, {
key: 'chunksUploading',
get: function get() {
return this.chunks.filter(function (chunk) {
return !!chunk.xhr && !!chunk.active;
});
}
/**
* Gets all the chunks that have finished uploading
*/
}, {
key: 'chunksUploaded',
get: function get() {
return this.chunks.filter(function (chunk) {
return !!chunk.uploaded;
});
}
}]);
return ChunkUploadHandler;
}();
//
//
//
//
//
//
//
//
//
//
//
//
//
var script = {
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
});
}
}
};
/* script */
var __vue_script__ = script;
/* template */
var __vue_render__ = function __vue_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, "capture": _vm.$parent.capture, "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 } });
};
var __vue_staticRenderFns__ = [];
/* style */
var __vue_inject_styles__ = undefined;
/* scoped */
var __vue_scope_id__ = undefined;
/* module identifier */
var __vue_module_identifier__ = undefined;
/* functional template */
var __vue_is_functional_template__ = false;
/* component normalizer */
function __vue_normalize__(template, style, script$$1, scope, functional, moduleIdentifier, createInjector, createInjectorSSR) {
var component = (typeof script$$1 === 'function' ? script$$1.options : script$$1) || {};
if (!component.render) {
component.render = template.render;
component.staticRenderFns = template.staticRenderFns;
component._compiled = true;
if (functional) component.functional = true;
}
component._scopeId = scope;
return component;
}
/* style inject */
function __vue_create_injector__() {
var head = document.head || document.getElementsByTagName('head')[0];
var styles = __vue_create_injector__.styles || (__vue_create_injector__.styles = {});
var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
return function addStyle(id, css) {
if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return; // SSR styles are present.
var group = isOldIE ? css.media || 'default' : id;
var style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
if (!style.ids.includes(id)) {
var code = css.source;
var index = style.ids.length;
style.ids.push(id);
if (css.map) {
// https://developer.chrome.com/devtools/docs/javascript-debugging
// this makes source maps inside style tags work properly in Chrome
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */';
// http://stackoverflow.com/a/26603875
code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */';
}
if (isOldIE) {
style.element = style.element || document.querySelector('style[data-group=' + group + ']');
}
if (!style.element) {
var el = style.element = document.createElement('style');
el.type = 'text/css';
if (css.media) el.setAttribute('media', css.media);
if (isOldIE) {
el.setAttribute('data-group', group);
el.setAttribute('data-next-index', '0');
}
head.appendChild(el);
}
if (isOldIE) {
index = parseInt(style.element.getAttribute('data-next-index'));
style.element.setAttribute('data-next-index', index + 1);
}
if (style.element.styleSheet) {
style.parts.push(code);
style.element.styleSheet.cssText = style.parts.filter(Boolean).join('\n');
} else {
var textNode = document.createTextNode(code);
var nodes = style.element.childNodes;
if (nodes[index]) style.element.removeChild(nodes[index]);
if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode);
}
}
};
}
/* style inject SSR */
var InputFile = __vue_normalize__({ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, __vue_create_injector__, undefined);
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); } }
var CHUNK_DEFAULT_OPTIONS = {
headers: {},
action: '',
minSize: 1048576,
maxActive: 3,
maxRetries: 5,
handler: ChunkUploadHandler
};
var script$1 = {
components: {
InputFile: InputFile
},
props: {
inputId: {
type: String
},
name: {
type: String,
default: 'file'
},
accept: {
type: String
},
capture: {},
multiple: {
type: Boolean
},
maximum: {
type: Number,
default: function _default() {
return this.multiple ? 0 : 1;
}
},
addIndex: {
type: [Boolean, Number]
},
directory: {
type: Boolean
},
postAction: {
type: String
},
putAction: {
type: String
},
customAction: {
type: Function
},
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
},
// Chunk upload enabled
chunkEnabled: {
type: Boolean,
default: false
},
// Chunk upload properties
chunk: {
type: Object,
default: function _default() {
return CHUNK_DEFAULT_OPTIONS;
}
}
},
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;
},
chunkOptions: function chunkOptions() {
return Object.assign(CHUNK_DEFAULT_OPTIONS, this.chunk);
},
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) ; 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;
}
// 最大数量限制
if (this.maximum > 1 && addFiles.length + this.files.length >= this.maximum) {
break;
}
addFiles.push(file);
// 最大数量限制
if (this.maximum === 1) {
break;
}
}
// 没有文件
if (!addFiles.length) {
return false;
}
// 如果是 1 清空
if (this.maximum === 1) {
this.clear();
}
// 添加进去 files
var newFiles = void 0;
if (index === true || index === 0) {
newFiles = addFiles.concat(this.files);
} else if (index) {
var _newFiles;
newFiles = this.files.concat([]);
(_newFiles = newFiles).splice.apply(_newFiles, [index, 0].concat(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 {
var names = el.value.replace(/\\/g, '/').split('/');
files.push({
name: names[names.length - 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() || item.getAsFile();
} else if (item.webkitGetAsEntry) {
item = item.webkitGetAsEntry() || item.getAsFile();
} 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.maximum > 0 && files.length >= _this.maximum) {
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.maximum > 0 && files.length >= this.maximum) {
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) {
var files = [];
var dirReader = entry.createReader();
var readEntries = function readEntries() {
dirReader.readEntries(function (entries) {
var forEach = function forEach(i) {
if (!entries[i] && i === 0 || _this2.maximum > 0 && files.length >= _this2.maximum) {
return resolve(files);
}
if (!entries[i]) {
return readEntries();
}
_this2.getEntry(entries[i], path + entry.name + '/').then(function (results) {
files.push.apply(files, _toConsumableArray(results));
forEach(i + 1);
});
};
forEach(0);
});
};
readEntries();
} 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.customAction) {
return this.customAction(file, this);
}
if (this.features.html5) {
if (this.shouldUseChunkUpload(file)) {
return this.uploadChunk(file);
}
if (file.putAction) {
return this.uploadPut(file);
}
if (file.postAction) {
return this.uploadHtml5(file);
}
}
if (file.postAction) {
return this.uploadHtml4(file);
}
return Promise.reject('No action configured');
},
/**
* Whether this file should be uploaded using chunk upload or not
*
* @param Object file
*/
shouldUseChunkUpload: function shouldUseChunkUpload(file) {
return this.chunkEnabled && !!this.chunkOptions.handler && file.size > this.chunkOptions.minSize;
},
/**
* Upload a file using Chunk method
*
* @param File file
*/
uploadChunk: function uploadChunk(file) {
var HandlerClass = this.chunkOptions.handler;
file.chunk = new HandlerClass(file, this.chunkOptions);
return file.chunk.upload();
},
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') {
if (value instanceof File) {
form.append(key, value, value.name);
} else {
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;
input.value = value;
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);
document.removeEventListener('drop', this.onDocumentDrop, 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);
document.addEventListener('drop', this.onDocumentDrop, false);
this.dropElement.addEventListener('dragover', this.onDragover, false);
this.dropElement.addEventListener('drop', this.onDrop, false);
}
},
onDragenter: function onDragenter(e) {
e.preventDefault();
if (this.dropActive) {
return;
}
if (!e.dataTransfer) {
return;
}
var dt = e.dataTransfer;
if (dt.files && dt.files.length) {
this.dropActive = true;
} else if (!dt.types) {
this.dropActive = true;
} else if (dt.types.indexOf && dt.types.indexOf('Files') !== -1) {
this.dropActive = true;
} else if (dt.types.contains && dt.types.contains('Files')) {
this.dropActive = true;
}
},
onDragleave: function onDragleave(e) {
e.preventDefault();
if (!this.dropActive) {
return;
}
if (e.target.nodeName === 'HTML' || e.target === e.explicitOriginalTarget || e.screenX === 0 && e.screenY === 0 && !e.fromElement && e.offsetX <= 0) {
this.dropActive = false;
}
},
onDragover: function onDragover(e) {
e.preventDefault();
},
onDocumentDrop: function onDocumentDrop() {
this.dropActive = false;
},
onDrop: function onDrop(e) {
e.preventDefault();
this.addDataTransfer(e.dataTransfer);
}
}
};
/* script */
var __vue_script__$1 = script$1;
/* template */
var __vue_render__$1 = function __vue_render__() {
var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('span', { class: _vm.className }, [_vm._t("default"), _vm._v(" "), _c('label', { attrs: { "for": _vm.inputId || _vm.name } }), _vm._v(" "), _c('input-file')], 2);
};
var __vue_staticRenderFns__$1 = [];
/* style */
var __vue_inject_styles__$1 = undefined;
/* scoped */
var __vue_scope_id__$1 = undefined;
/* module identifier */
var __vue_module_identifier__$1 = undefined;
/* functional template */
var __vue_is_functional_template__$1 = false;
/* component normalizer */
function __vue_normalize__$1(template, style, script, scope, functional, moduleIdentifier, createInjector, createInjectorSSR) {
var component = (typeof script === 'function' ? script.options : script) || {};
if (!component.render) {
component.render = template.render;
component.staticRenderFns = template.staticRenderFns;
component._compiled = true;
if (functional) component.functional = true;
}
component._scopeId = scope;
return component;
}
/* style inject */
function __vue_create_injector__$1() {
var head = document.head || document.getElementsByTagName('head')[0];
var styles = __vue_create_injector__$1.styles || (__vue_create_injector__$1.styles = {});
var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
return function addStyle(id, css) {
if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return; // SSR styles are present.
var group = isOldIE ? css.media || 'default' : id;
var style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
if (!style.ids.includes(id)) {
var code = css.source;
var index = style.ids.length;
style.ids.push(id);
if (css.map) {
// https://developer.chrome.com/devtools/docs/javascript-debugging
// this makes source maps inside style tags work properly in Chrome
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */';
// http://stackoverflow.com/a/26603875
code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */';
}
if (isOldIE) {
style.element = style.element || document.querySelector('style[data-group=' + group + ']');
}
if (!style.element) {
var el = style.element = document.createElement('style');
el.type = 'text/css';
if (css.media) el.setAttribute('media', css.media);
if (isOldIE) {
el.setAttribute('data-group', group);
el.setAttribute('data-next-index', '0');
}
head.appendChild(el);
}
if (isOldIE) {
index = parseInt(style.element.getAttribute('data-next-index'));
style.element.setAttribute('data-next-index', index + 1);
}
if (style.element.styleSheet) {
style.parts.push(code);
style.element.styleSheet.cssText = style.parts.filter(Boolean).join('\n');
} else {
var textNode = document.createTextNode(code);
var nodes = style.element.childNodes;
if (nodes[index]) style.element.removeChild(nodes[index]);
if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode);
}
}
};
}
/* style inject SSR */
var FileUpload = __vue_normalize__$1({ render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, __vue_inject_styles__$1, __vue_script__$1, __vue_scope_id__$1, __vue_is_functional_template__$1, __vue_module_identifier__$1, __vue_create_injector__$1, undefined);
var FileUpload$1 = /*#__PURE__*/Object.freeze({
default: FileUpload
});
var require$$0 = ( FileUpload$1 && FileUpload ) || FileUpload$1;
var src = require$$0;
return src;
})));
//# sourceMappingURL=vue-upload-component.part.js.map