v2.0.0-beta

master v2.0.0-beta
git 9 years ago
parent 601c0c403b
commit bc24562a12

@ -8,8 +8,9 @@
## Install ## Install
``` bash ``` bash
npm install vue-upload-component --save npm install vue-upload-component@next --save
``` ```
### CommonJS ### CommonJS
```js ```js
var FileUpload = require('vue-upload-component'); var FileUpload = require('vue-upload-component');
@ -73,93 +74,119 @@ npm run build
``` ```
## $dispatch, methods
addFileUpload
removeFileUpload # Setting
fileUploadProgress
beforeFileUpload ## Props
``` html
<file-upload
title="Add upload files"
afterFileUpload name="post file name"
drop="Boolean (true = $parent) or Element or Css Selector"
extensions="Array or String or Regular"
post-action="./post.method"
## Setting put-action="./put.method"
### Data accept="accept"
``` js
{
files: [
{
id: 'String', // Read only
name: 'filename String',
size: 'filesize Number',
progress: 'progress String', // Read only
speed: "Speed Number", // Read only
active: 'active Boolean',
error: 'error String',
errno: 'errno String',
success: 'success Boolean', // Read only
data: 'Response data Object or String', // Read only
request: {
headers: {
"X-Csrf-Token": "xxxx",
},
data: {
"_csrf_token": "xxxxxx",
},
},
}
],
multiple="true or false"
// Global size="max Size"
request: {
headers: {
"X-Csrf-Token": "xxxx",
},
data: {
"_csrf_token": "xxxxxx",
},
},
timeout="3600000"
active: false, events="Object"
uploaded: true, // Read only headers="Request headers object"
dropActive: false, // Read only data="Request data object"
}
files="Upload files"
>
</file-upload>
``` ```
### Props
``` html
<file-upload :title="Add upload files" :name="file" :drop="Boolean (true = $parent) or Element or Css Selector" :extensions="Array or String or Regular" :post-action="./post.method" :put-action="./put.method" :accept="accept" :multiple="true" :size="size" :timeout="3600000"></file-upload>
```
### Props events
``` js
events: {
add(file, component) {
console.log('add');
if (this.auto) {
component.active = true;
}
file.headers['X-Filename'] = encodeURIComponent(file.name)
file.data.finename = file.name
// file.putAction = 'xxx'
// file.postAction = 'xxx'
},
progress(file, component) {
console.log('progress ' + file.progress);
},
after(file, component) {
console.log('after');
},
before(file, component) {
console.log('before');
}
}
``` ```
title="Add upload files"
name="post file name"
drop="Boolean (true = $parent) or Element or Css Selector"
extensions="Array or String or Regular" :post-action="./post.method" ### Props files
``` js
[
{
id: 'String', // Read only
name: 'filename String',
size: 'filesize Number', // -1 = html4
progress: 'progress String', // Read only
speed: "Speed Number", // Read only
active: 'active Boolean', // set active = fasle abort upload
error: 'error String', // Read only
success: 'success Boolean', // Read only
data: 'Response data Object or String', // Read only
putAction: 'String uri',
postAction: 'String uri',
timeout: "Number",
headers: {
"X-Csrf-Token": "xxxx",
},
data: {
"_csrf_token": "xxxxxx",
},
xhr: "False or XMLHttpRequest object", // html5
iframe: "False or Element object", // html4
file: "undefined or File object" // html5
el: "undefined or Input object"
}
]
```
post-action="./post.method"
put-action="./put.method"
accept="accept"
multiple="true or false"
size="max Size" ## data
``` js
{
mode: 'html5', // html5 or html4
timeout="3600000" active: false, // set active = fasle abort upload
uploaded: true, // Read only
dropActive: false, // Read only
}
``` ```

19458
dist/example.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -41,15 +41,14 @@
<th>Speed</th> <th>Speed</th>
<th>Active</th> <th>Active</th>
<th>Error</th> <th>Error</th>
<th>Errno</th>
<th>Success</th> <th>Success</th>
<th>Abort</th> <th>Abort</th>
<th>Delete</th> <th>Delete</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="file in files"> <tr v-for="(file, index) in files">
<td>{{$index}}</td> <td>{{index}}</td>
<td>{{file.id}}</td> <td>{{file.id}}</td>
<td>{{file.name}}</td> <td>{{file.name}}</td>
<td>{{file.size | formatSize}}</td> <td>{{file.size | formatSize}}</td>
@ -57,7 +56,6 @@
<td>{{file.speed | formatSize}}</td> <td>{{file.speed | formatSize}}</td>
<td>{{file.active}}</td> <td>{{file.active}}</td>
<td>{{file.error}}</td> <td>{{file.error}}</td>
<td>{{file.errno}}</td>
<td>{{file.success}}</td> <td>{{file.success}}</td>
<td @click="file.active = false">Abort</td> <td @click="file.active = false">Abort</td>
<td @click="remove(file)">x</td> <td @click="remove(file)">x</td>
@ -70,11 +68,27 @@
<tbody> <tbody>
<tr> <tr>
<td> <td>
<file-upload title="Add upload files" class="file-upload" name="file" post-action="./post.php" put-action="./put.php" :extensions="extensions" :accept="accept" :multiple="multiple" :size="size" v-ref:upload :drop="drop"></file-upload> <file-upload
:title="title"
class="file-upload"
:events="events"
:name="name"
:post-action="postAction"
:put-action="putAction"
:extensions="extensions"
:accept="accept"
:multiple="multiple"
:size="size"
:headers="headers"
:data="data"
:drop="drop"
:files="files"
ref="upload">
</file-upload>
</td> </td>
<td> <td>
<button v-if="upload.active" type="submit" @click.prevent="$refs.upload.active = !$refs.upload.active">Stop upload</button> <button v-if="upload.active" type="submit" @click.prevent="upload.active = !upload.active">Stop upload</button>
<button v-else type="submit" @click.prevent="$refs.upload.active = !$refs.upload.active">Start upload</button> <button v-else type="submit" @click.prevent="upload.active = !upload.active">Start upload</button>
</td> </td>
<td> <td>
<label> <label>
@ -98,7 +112,7 @@
</td> </td>
<td> <td>
<label> <label>
Max file size: <input type="text" v-model="size"> Max file size: <input type="text" v-model.number="size">
</label> </label>
</td> </td>
<td> <td>
@ -112,18 +126,18 @@
Auto start: {{auto}} Auto start: {{auto}}
</td> </td>
<td> <td>
Active: {{$refs.upload.active}} Active: {{upload.active}}
</td> </td>
<td> <td>
Uploaded: {{$refs.upload.uploaded}} Uploaded: {{upload.uploaded}}
</td> </td>
<td> <td>
Drop active: {{$refs.upload.dropActive}} Drop active: {{upload.dropActive}}
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div v-show="$refs.upload.dropActive" class="drop-active"> <div v-show="upload.dropActive" class="drop-active">
Drop ing Drop ing
</div> </div>
</div> </div>

@ -1,7 +1,7 @@
{ {
"name": "vue-upload-component", "name": "vue-upload-component",
"description": "Vue.js file upload component, Support for multiple file uploads, progress, html5, html4, support ie9", "description": "Vue.js file upload component, Support for multiple file uploads, progress, html5, html4, support ie9",
"version": "0.3.7", "version": "2.0.0-beta",
"author": "LianYue", "author": "LianYue",
"scripts": { "scripts": {
"dev": "webpack-dev-server --inline --hot", "dev": "webpack-dev-server --inline --hot",
@ -30,24 +30,28 @@
"url": "https://github.com/lian-yue/vue-upload-component/issues" "url": "https://github.com/lian-yue/vue-upload-component/issues"
}, },
"homepage": "https://github.com/lian-yue/vue-upload-component#readme", "homepage": "https://github.com/lian-yue/vue-upload-component#readme",
"dependencies": { "dependencies": {},
},
"devDependencies": { "devDependencies": {
"babel-core": "^6.0.0", "babel-core": "^6.0.0",
"babel-helper-vue-jsx-merge-props": "^2.0.1",
"babel-loader": "^6.0.0", "babel-loader": "^6.0.0",
"babel-plugin-syntax-jsx": "^6.13.0",
"babel-plugin-transform-runtime": "^6.0.0", "babel-plugin-transform-runtime": "^6.0.0",
"babel-plugin-transform-vue-jsx": "^3.1.0",
"babel-preset-es2015": "^6.0.0", "babel-preset-es2015": "^6.0.0",
"babel-preset-stage-0": "^6.5.0",
"babel-preset-stage-2": "^6.0.0", "babel-preset-stage-2": "^6.0.0",
"babel-runtime": "^6.0.0", "babel-runtime": "^6.0.0",
"cross-env": "^1.0.6", "cross-env": "^1.0.6",
"css-loader": "^0.23.0", "css-loader": "^0.23.0",
"expose-loader": "^0.7.1",
"file-loader": "^0.8.4", "file-loader": "^0.8.4",
"json-loader": "^0.5.4", "json-loader": "^0.5.4",
"url-loader": "^0.5.7", "url-loader": "^0.5.7",
"vue": "^1.0.26", "vue": "^2.0.0-rc.6",
"vue-hot-reload-api": "^1.2.0", "vue-hot-reload-api": "^1.2.0",
"vue-html-loader": "^1.0.0", "vue-html-loader": "^1.0.0",
"vue-loader": "^8.2.1", "vue-loader": "^9.5.0",
"vue-style-loader": "^1.0.0", "vue-style-loader": "^1.0.0",
"webpack": "^1.12.2", "webpack": "^1.12.2",
"webpack-dev-server": "^1.12.0" "webpack-dev-server": "^1.12.0"

@ -1,10 +1,3 @@
<template>
<label :class="{'file-uploads': true, 'file-uploads-html5': $mode == 'html5', 'file-uploads-html4': $mode == 'html4'}">
<span>{{title}}</span>
<input-file></input-file>
</label>
</template>
<style> <style>
.file-uploads { .file-uploads {
overflow: hidden; overflow: hidden;
@ -42,7 +35,12 @@
</style> </style>
<script> <script>
import InputFile from './InputFile.vue';
export default { export default {
components: {
InputFile,
},
props: { props: {
title: { title: {
type: String, type: String,
@ -81,58 +79,75 @@ export default {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
},
components: { headers: {
inputFile : { type: Object,
template: '<input type="file" :name="$parent.name" :id="$parent.id||$parent.name" :accept="$parent.accept" @change="change" :multiple="$parent.multiple && $parent.$mode == \'html5\'">', default: () => {},
methods: { },
change(e) { data: {
this.$parent._addFileUploads(e.target); type: Object,
this.$destroy(); default: () => {},
}, },
}, drop: {
type: Boolean,
default: false,
},
files: {
type: Array,
default: () => [],
}, },
}, },
data() { data() {
return { return {
files: [], mode: 'html5',
active: false, active: false,
uploaded: true, uploaded: true,
dropActive: false, dropActive: false,
dropElement: false,
request: {
data: {},
headers: {},
},
} }
}, },
ready() { //
this._drop(this.drop); mounted() {
},
init() {
var input = document.createElement('input'); var input = document.createElement('input');
input.type = 'file'; input.type = 'file';
if (window.FormData && input.files) { if (window.FormData && input.files) {
this.$mode = 'html5'; this.mode = 'html5';
} else { } else {
this.$mode = 'html4'; this.mode = 'html4';
} }
this._index = 0; this._index = 0;
this._files = [];
this._dropActive = 0; this._dropActive = 0;
this._files = {}; this._drop(this.drop)
this.$nextTick(() => {
this._drop(this.drop)
})
}, },
//
beforeDestroy() { beforeDestroy() {
this.active = false; this.active = false;
this.files = []; this.files = [];
}, },
render (h) {
return (
<label class={{
'file-uploads': true,
'file-uploads-html5': this.mode == 'html5',
'file-uploads-html4': this.mode == 'html4'
}} >
<span>{this.title}</span>
<input-file></input-file>
</label>
)
},
watch: { watch: {
drop(value) { drop(value) {
this._drop(value); this._drop(value);
@ -140,36 +155,38 @@ export default {
files(files) { files(files) {
var ids = []; var ids = [];
for (var i = 0; i < files.length; i++) { for (var i = 0; i < files.length; i++) {
var file = files[i]; let file = files[i];
if (!file.errno && !file.success) { if (!file.error && !file.success) {
this.uploaded = false; this.uploaded = false;
} }
ids.push(file.id); ids.push(file.id);
} }
for (var id in this._files) { for (var id in this._files) {
if (ids.indexOf(id) != -1) { if (ids.indexOf(id) != -1) {
continue; continue;
} }
let file = this._files;
//
var file = this._files[id]._file;
file.removed = true; file.removed = true;
var xhr = this._files[id].xhr;
// xhr abort
var xhr = file.xhr;
if (xhr) { if (xhr) {
try { try {
xhr.abort(); xhr.abort();
xhr.timeout = 1; xhr.timeout = 1;
} catch (e) { } catch (e) {
} }
} }
var iframe = this._files[id].iframe;
if (iframe) { // iframe abort
iframe.onabort({type:'abort'}); if (file.iframe) {
file.iframe.onabort({type:'abort'});
} }
delete this._files[id]; delete this._files[id];
this._uploadEvents('removeFileUpload', file); this._uploadEvents('remove', file);
} }
this._index = 0; this._index = 0;
}, },
@ -194,14 +211,51 @@ export default {
} }
}, },
addFileUpload(file) {
this.uploaded = false;
var defaultFile = {
size: -1,
name: 'Filename',
progress: '0.00',
speed: 0,
active: false,
error: '',
success: false,
putAction: this.putAction,
postAction: this.postAction,
timeout: this.timeout,
data: Object.assign({}, this.data),
headers: Object.assign({}, this.headers),
response: {},
xhr: false,
iframe: false,
};
file = Object.assign(defaultFile, file)
if (!file.id) {
file.id = Math.random().toString(36).substr(2);
}
if (!this.multiple) {
this.clear();
}
file = this.files[this.files.push(file) - 1];
this._files[file.id] = file;
this._uploadEvents('add', file);
},
_uploadEvents(name, file) { _uploadEvents(name, file) {
this.$dispatch && this.$dispatch(name, file, this);
this[name] && this[name](file);
this.events && this.events[name] && this.events[name](file, this); this.events && this.events[name] && this.events[name](file, this);
}, },
_drop(value) { _drop(value) {
if (this.dropElement && this.$mode === 'html5') {
//
if (this.dropElement && this.mode === 'html5') {
try { try {
window.document.removeEventListener('dragenter', this._onDragenter, false); window.document.removeEventListener('dragenter', this._onDragenter, false);
window.document.removeEventListener('dragleave', this._onDragleave, false); window.document.removeEventListener('dragleave', this._onDragleave, false);
@ -223,18 +277,21 @@ export default {
} else { } else {
this.dropElement = this.drop; this.dropElement = this.drop;
} }
if (this.dropElement && this.$mode === 'html5') {
if (this.dropElement && this.mode === 'html5') {
window.document.addEventListener('dragenter', this._onDragenter, false); window.document.addEventListener('dragenter', this._onDragenter, false);
window.document.addEventListener('dragleave', this._onDragleave, false); window.document.addEventListener('dragleave', this._onDragleave, false);
this.dropElement.addEventListener('dragover', this._onDragover, false); this.dropElement.addEventListener('dragover', this._onDragover, false);
this.dropElement.addEventListener('drop', this._onDrop, false); this.dropElement.addEventListener('drop', this._onDrop, false);
} }
}, },
_onDragenter(e) { _onDragenter(e) {
this._dropActive++; this._dropActive++;
this.dropActive = !!this._dropActive; this.dropActive = !!this._dropActive;
e.preventDefault(); e.preventDefault();
}, },
_onDragleave(e) { _onDragleave(e) {
e.preventDefault(); e.preventDefault();
this._dropActive--; this._dropActive--;
@ -246,40 +303,7 @@ export default {
e.preventDefault(); e.preventDefault();
}, },
_addFileUpload(hiddenData, file) {
var defaultFile = {
size:-1,
name: 'Filename',
progress: '0.00',
speed: 0,
active: false,
error: '',
errno: '',
success: false,
data: {},
request: {
headers:{},
data:{}
}
};
for (let key in defaultFile) {
if (typeof file[key] == 'undefined') {
file[key] = defaultFile[key];
}
}
if (!file.id) {
file.id = Math.random().toString(36).substr(2);
}
if (!this.multiple) {
this.clear();
}
this._files[file.id] = hiddenData;
file = this.files[this.files.push(file) - 1];
this._files[file.id]._file = file;
this._uploadEvents('addFileUpload', file);
},
_onDrop(e) { _onDrop(e) {
this._dropActive = 0; this._dropActive = 0;
this.dropActive = false; this.dropActive = false;
@ -287,7 +311,7 @@ export default {
if (e.dataTransfer.files.length) { if (e.dataTransfer.files.length) {
for (let i = 0; i < e.dataTransfer.files.length; i++) { for (let i = 0; i < e.dataTransfer.files.length; i++) {
let file = e.dataTransfer.files[i]; let file = e.dataTransfer.files[i];
this._addFileUpload({file:file}, {size:file.size, name: file.name}); this.addFileUpload({file:file, size:file.size, name: file.name});
if (!this.multiple) { if (!this.multiple) {
break; break;
} }
@ -295,102 +319,106 @@ export default {
} }
}, },
_addFileUploads(el) {
var Component = this.$options.components.inputFile;
new Component({
parent: this,
el: el,
});
this.uploaded = false;
_addInputFileElement(el) {
if (el.files) { if (el.files) {
for (let i = 0; i < el.files.length; i++) { for (let i = 0; i < el.files.length; i++) {
let file = el.files[i]; let file = el.files[i];
this._addFileUpload({file:file, el:el}, {size:file.size, name: file.name}); this.addFileUpload({size: file.size, name: file.name, file: file, el:el});
} }
} else { } else {
this._addFileUpload({el:el}, {size: -1, name: el.value.replace(/^.*?([^\/\\\r\n]+)$/, '$1')}); this.addFileUpload({name: el.value.replace(/^.*?([^\/\\\r\n]+)$/, '$1'), el:el});
} }
var Component = this.$options.components.InputFile;
var inputFile = new Component({
parent: this,
el: el,
});
}, },
_fileUploads() { _fileUploads() {
if (!this.active) { if (!this.active) {
return; return;
} }
for (; this._index < this.files.length; this._index++) { for (; this._index < this.files.length; this._index++) {
var file = this.files[this._index]; var file = this.files[this._index];
if (file.active || file.success || file.errno) { if (file.active || file.success || file.error) {
continue; continue;
} }
if (this.size && this.size > 0 && file.size >= 0 && file.size > this.size) { if (this.size && this.size > 0 && file.size >= 0 && file.size > this.size) {
file.error = 'Size'; file.error = 'size';
file.errno = 'size';
continue; continue;
} }
if (this.extensions && (this.extensions.length || typeof this.extensions.length == 'undefined')) { if (this.extensions && (this.extensions.length || typeof this.extensions.length == 'undefined')) {
var extensions = this.extensions; var extensions = this.extensions;
if (typeof extensions == 'object' && extensions instanceof RegExp) { if (typeof extensions == 'object' && extensions instanceof RegExp) {
} else { } else {
if (typeof extensions == 'string') { if (typeof extensions == 'string') {
extensions = extensions.split(',').map(function(value) { extensions = extensions.split(',').map((value) => value.trim()).filter(value => value);
return value.trim();
}).filter(function(value) {
return value;
});
} }
extensions = new RegExp('\\.('+ extensions.join('|').replace(/\./g, '\\.') +')$', 'i'); extensions = new RegExp('\\.('+ extensions.join('|').replace(/\./g, '\\.') +')$', 'i');
} }
if (file.name.search(extensions) == -1) { if (file.name.search(extensions) == -1) {
file.error = 'Extension'; file.error = 'extension';
file.errno = 'extension';
continue; continue;
} }
} }
if (this.$mode == 'html5') { if (this.mode == 'html5') {
if (this.putAction || file.putAction) { if (file.putAction) {
this._fileUploadPut(file); this._fileUploadPut(file);
} else if (this.postAction || file.postAction) { } else if (file.postAction) {
this._fileUploadHtml5(file); this._fileUploadHtml5(file);
} else { } else {
file.error = 'Not Support'; file.error = 'not_support';
file.errno = 'not_support';
continue; continue;
} }
} else { } else {
if (this.postAction || file.postAction) { if (file.postAction) {
this._fileUploadHtml4(file); this._fileUploadHtml4(file);
} else { } else {
file.error = 'Not Support'; file.error = 'not_support';
file.errno = 'not_support';
continue; continue;
} }
} }
return; return;
} }
this.active = false; this.active = false;
this.uploaded = true; this.uploaded = true;
}, },
_fileUploadXhr(xhr, file, data) { _fileUploadXhr(xhr, file, data) {
var _self = this; var _self = this;
var hiddenData = this._files[file.id]; var complete = false;
var fileUploads = false;
var speedTime = 0; var speedTime = 0;
var speedLoaded = 0; var speedLoaded = 0;
xhr.upload.onprogress = function(e) { xhr.upload.onprogress = function(e) {
//
if (file.removed) { if (file.removed) {
xhr.abort(); xhr.abort();
return; return;
} }
//
if (!_self.active || !file.active) { if (!_self.active || !file.active) {
xhr.abort(); xhr.abort();
return; return;
} }
//
if (e.lengthComputable) { if (e.lengthComputable) {
file.progress = (e.loaded / e.total * 100).toFixed(2); file.progress = (e.loaded / e.total * 100).toFixed(2);
var speedTime2 = Math.round(Date.now() / 1000); var speedTime2 = Math.round(Date.now() / 1000);
@ -400,196 +428,166 @@ export default {
speedTime = speedTime2; speedTime = speedTime2;
} }
} }
_self._uploadEvents('fileUploadProgress', file); _self._uploadEvents('progress', file);
}; }
var callback = function(e) { var callback = function(e) {
switch (e.type) { switch (e.type) {
case 'timeout': case 'timeout':
file.errno = 'timeout'; file.error = 'timeout';
file.error = 'Timeout';
break; break;
case 'abort': case 'abort':
file.errno = 'abort'; file.error = 'abort';
file.error = 'Abort';
break; break;
case 'error': case 'error':
if (!xhr.status) { if (!xhr.status) {
file.errno = 'network'; file.error = 'network';
file.error = 'Network';
} else if(xhr.status >= 500) { } else if(xhr.status >= 500) {
file.errno = 'server'; file.error = 'server';
file.error = 'Server';
} else if (xhr.status >= 400) { } else if (xhr.status >= 400) {
file.errno = 'denied'; file.error = 'denied';
file.error = 'Denied';
} }
break; break;
default: default:
if(xhr.status >= 500) { if(xhr.status >= 500) {
file.errno = 'server'; file.error = 'server';
file.error = 'Server';
} else if (xhr.status >= 400) { } else if (xhr.status >= 400) {
file.errno = 'denied'; file.error = 'denied';
file.error = 'Denied';
} else { } else {
file.progress = '100.00'; file.progress = '100.00';
file.success = true; file.success = true;
} }
}
file.active = false;
if (xhr.responseText) {
var contentType = xhr.getResponseHeader('Content-Type');
if (contentType && contentType.indexOf('/json') != -1) {
file.response = JSON.parse(xhr.responseText);
} else {
file.response = xhr.responseText;
} }
file.active = false; }
if (xhr.responseText) {
var contentType = xhr.getResponseHeader('Content-Type'); if (!complete) {
if (contentType && contentType.indexOf('/json') != -1) { complete = true;
file.data = JSON.parse(xhr.responseText); if (!file.removed) {
} else { _self._uploadEvents('after', file);
file.data = xhr.responseText;
}
}
if (!fileUploads) {
fileUploads = true;
if (!file.removed) {
_self._uploadEvents('afterFileUpload', file);
}
setTimeout(function() {
_self._fileUploads();
}, 50);
} }
setTimeout(function() {
_self._fileUploads();
}, 50);
}
}; };
//
xhr.onload = callback; xhr.onload = callback;
xhr.onerror = callback; xhr.onerror = callback;
xhr.onabort = callback; xhr.onabort = callback;
xhr.ontimeout = callback; xhr.ontimeout = callback;
//
if (this.timeout) { if (file.timeout) {
xhr.timeout = this.timeout; xhr.timeout = file.timeout;
} }
xhr.onload = callback;
xhr.onerror = callback;
xhr.onabort = callback;
xhr.ontimeout = callback;
if (this.timeout) {
xhr.timeout = this.timeout;
}
// headers
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
for (var key in this.request.headers) { for (let key in file.headers) {
xhr.setRequestHeader(key, this.request.headers[key]); xhr.setRequestHeader(key, file.headers[key]);
}
for (var key in file.request.headers) {
xhr.setRequestHeader(key, file.request.headers[key]);
} }
//
xhr.send(data); xhr.send(data);
file.active = true; file.active = true;
hiddenData.xhr = xhr; file.xhr = xhr
//
var interval = setInterval(function() { var interval = setInterval(function() {
if (!_self.active || !file.active || file.success || file.errno) { if (!_self.active || !file.active || file.success || file.error) {
clearInterval(interval); clearInterval(interval);
if (!file.success && !file.errno) { if (!file.success && !file.error) {
xhr.abort(); xhr.abort();
} }
} }
}, 100); }, 100);
this._uploadEvents('beforeFileUpload', file);
},
_fileUploadPut(file) {
var _self = this;
var querys = {};
for (let key in this.request.data) {
querys[key] = this.request.data[key];
}
for (let key in file.request.data) {
querys[key] = file.request.data[key];
}
var queryArray = [];
for (let key in querys) {
if (querys[key] !== null && typeof querys[key] !== 'undefined') {
queryArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(querys[key]));
}
}
var queryString = queryArray.length ? '?' + queryArray.join('&') : '';
var xhr = new XMLHttpRequest(); //
xhr.open('PUT', (file.putAction || this.putAction) + queryString); this._uploadEvents('before', file);
this._fileUploadXhr(xhr, file, this._files[file.id].file);
}, },
_fileUploadPut(file) {
var querys = Object.assign({}, file.data)
var queryArray = [];
for (let key in querys) {
if (querys[key] !== null && typeof querys[key] !== 'undefined') {
queryArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(querys[key]));
}
}
var queryString = queryArray.length ? (file.putAction.indexOf('?') == -1 ? '?' : '&') + queryArray.join('&') : '';
var xhr = new XMLHttpRequest();
xhr.open('PUT', file.putAction + queryString);
this._fileUploadXhr(xhr, file, file.file);
},
_fileUploadHtml5(file) { _fileUploadHtml5(file) {
var form = new window.FormData(); var form = new window.FormData();
form.append(this.name, this._files[file.id].file); form.append(this.name, file.file);
for (var key in this.request.data) { for (var key in file.data) {
form.append(key, this.request.data[key]); form.append(key, file.data[key]);
} }
for (var key in file.request.data) {
form.append(key, file.request.data[key]);
}
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open('POST', file.postAction || this.postAction); xhr.open('POST', file.postAction);
this._fileUploadXhr(xhr, file, form); this._fileUploadXhr(xhr, file, form);
}, },
_fileUploadHtml4(file) { _fileUploadHtml4(file) {
var _self = this; var _self = this;
var hiddenData = this._files[file.id]; var complete = false;
var fileUploads = false;
var keydown = function(e) { var keydown = function(e) {
if (e.keyCode == 27) { if (e.keyCode == 27) {
e.preventDefault(); e.preventDefault();
} }
}; }
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
iframe.id = 'upload-iframe-' + file.id; iframe.id = 'upload-iframe-' + file.id;
iframe.name = 'upload-iframe-' + file.id; iframe.name = 'upload-iframe-' + file.id;
iframe.src = 'about:blank'; iframe.src = 'about:blank';
iframe.style.width = '1px'; iframe.style = {
iframe.style.height = '1px'; width: '1px',
iframe.style.top = '-9999px'; height: '1px',
iframe.style.left = '-9999px'; top: '-9999px',
iframe.style.position = 'absolute'; left: '-9999px',
iframe.style.marginTop = '-9999em'; position: 'absolute',
marginTop: '-9999em',
}
var form = document.createElement('form'); var form = document.createElement('form');
form.action = file.postAction || this.postAction;
form.action = file.postAction;
form.name = 'upload-form-' + file.id; form.name = 'upload-form-' + file.id;
form.setAttribute('method', 'POST'); form.setAttribute('method', 'POST');
form.setAttribute('target', 'upload-iframe-' + file.id); form.setAttribute('target', 'upload-iframe-' + file.id);
form.setAttribute('enctype', 'multipart/form-data'); form.setAttribute('enctype', 'multipart/form-data');
form.appendChild(hiddenData.el); form.appendChild(file.el);
for (var key in this.request.data) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = key;
input.value = this.request.data[key];
form.appendChild(input);
}
for (var key in file.request.data) { for (let key in file.data) {
var input = document.createElement('input'); let input = document.createElement('input');
input.type = 'hidden'; input.type = 'hidden';
input.name = key; input.name = key;
input.value = file.request.data[key]; input.value = file[key];
form.appendChild(input); form.appendChild(input);
} }
var getDocumentData = function() { var getDocumentData = function() {
var doc; var doc;
try { try {
@ -613,62 +611,58 @@ export default {
var callback = function(e) { var callback = function(e) {
switch (e.type) { switch (e.type) {
case 'abort': case 'abort':
file.errno = 'abort'; file.error = 'abort';
file.error = 'Abort';
break; break;
case 'error': case 'error':
var data = getDocumentData(); var data = getDocumentData();
if (file.errno) { if (file.error) {
} else if (data === null) { } else if (data === null) {
file.errno = 'network'; file.error = 'network';
file.error = 'Network';
} else { } else {
file.errno = 'denied'; file.error = 'denied';
file.error = 'Denied';
} }
break; break;
default: default:
var data = getDocumentData(); var data = getDocumentData();
if (file.errno) { if (file.error) {
} else if (data === null) {
} else if (data === null) { file.error = 'network';
file.errno = 'network'; } else {
file.error = 'Network'; file.progress = '100.00';
} else { file.success = true;
file.progress = '100.00'; }
file.success = true; }
}
}
file.active = false; file.active = false;
if (typeof data != "undefined") { if (typeof data != "undefined") {
if (data && data.substr(0, 1) == '{' && data.substr(data.length - 1, 1) == '}') { if (data && data.substr(0, 1) == '{' && data.substr(data.length - 1, 1) == '}') {
try { try {
data = JSON.parse(data); data = JSON.parse(data);
} catch (err) { } catch (err) {
}
} }
file.data = data;
} }
if (!fileUploads) { file.data = data;
document.body.removeEventListener('keydown', keydown); }
document.body.removeEventListener('keydown', keydown); if (!complete) {
fileUploads = true; complete = true;
iframe.parentNode && iframe.parentNode.removeChild(iframe); document.body.removeEventListener('keydown', keydown);
if (!file.removed) { document.body.removeEventListener('keydown', keydown);
_self._uploadEvents('afterFileUpload', file); iframe.parentNode && iframe.parentNode.removeChild(iframe);
} if (!file.removed) {
setTimeout(function() { _self._uploadEvents('after', file);
_self._fileUploads();
}, 50);
} }
setTimeout(function() {
_self._fileUploads();
}, 50);
}
}; };
setTimeout(function() { setTimeout(function() {
document.body.appendChild(iframe).appendChild(form).submit(); document.body.appendChild(iframe).appendChild(form).submit();
iframe.onload = callback; iframe.onload = callback;
@ -676,21 +670,21 @@ export default {
iframe.onabort = callback; iframe.onabort = callback;
file.active = true; file.active = true;
file.iframe = iframe;
hiddenData.iframe = iframe;
document.body.addEventListener('keydown', keydown); document.body.addEventListener('keydown', keydown);
var interval = setInterval(function() { var interval = setInterval(function() {
if (!_self.active || !file.active || file.success || file.errno) { if (!_self.active || !file.active || file.success || file.error) {
clearInterval(interval); clearInterval(interval);
if (!file.success && !file.errno) { if (!file.success && !file.error) {
iframe.onabort({type:'abort'}); iframe.onabort({type:'abort'});
} }
} }
}, 50); }, 50);
_self._uploadEvents('beforeFileUpload', file); _self._uploadEvents('before', file);
}, 10); }, 10);
}, },
} }
} }
</script> </script>

@ -0,0 +1,24 @@
<script>
export default {
methods: {
change(e) {
this.$destroy();
this.$parent._addInputFileElement(e.target);
},
},
render(h) {
const parent = this.$parent;
return (
<input
type="file"
name={parent.name}
id={parent.id|| parent.name}
accept={parent.accept}
on-change={this.change}
multiple={parent.multiple && parent.mode == 'html5'}
/>
)
}
}
</script>

@ -1,13 +1,14 @@
import Vue from 'vue'; import Vue from 'vue/dist/vue.js'
var FileUpload = require('./FileUpload.vue');
// import FileUpload from './FileUpload.vue';
// var FileUpload = require('./FileUpload.vue');
import FileUpload from './FileUpload.vue';
Vue.config.debug = true;
Vue.config.silent = false; Vue.config.silent = false;
Vue.config.async = false;
Vue.config.devtools = true; Vue.config.devtools = true;
Vue.filter('formatSize', function(size) { Vue.filter('formatSize', function(size) {
if (size > 1024 * 1024 * 1024 * 1024) { if (size > 1024 * 1024 * 1024 * 1024) {
return (size / 1024 / 1024 / 1024 / 1024).toFixed(2) + ' TB'; return (size / 1024 / 1024 / 1024 / 1024).toFixed(2) + ' TB';
@ -22,6 +23,8 @@ Vue.filter('formatSize', function(size) {
}); });
new Vue({ new Vue({
el:'#app', el:'#app',
components: { components: {
@ -35,43 +38,58 @@ new Vue({
// extensions: ['gif','jpg','png'], // extensions: ['gif','jpg','png'],
// extensions: /\.(gif|png|jpg)$/i, // extensions: /\.(gif|png|jpg)$/i,
files: [], files: [],
upload: {}, upload: [],
title: 'Add upload files',
drop: true, drop: true,
auto: false, auto: false,
},
compiled() { name: 'file',
this.upload = this.$refs.upload;
this.upload.request = { postAction: './post.php',
headers: { putAction: './put.php',
"X-Csrf-Token": "xxxx",
headers: {
"X-Csrf-Token": "xxxx",
},
data: {
"_csrf_token": "xxxxxx",
},
events: {
add(file, component) {
console.log('add');
if (this.auto) {
component.active = true;
}
file.headers['X-Filename'] = encodeURIComponent(file.name)
file.data.finename = file.name
// file.putAction = 'xxx'
// file.postAction = 'xxx'
}, },
data: { progress(file, component) {
"_csrf_token": "xxxxxx", console.log('progress ' + file.progress);
}, },
}; after(file, component) {
this.files = this.$refs.upload.files; console.log('after');
},
before(file, component) {
console.log('before');
},
}
},
mounted() {
this.upload = this.$refs.upload.$data
}, },
methods: { methods: {
remove(file) { remove(file) {
this.$refs.upload.files.$remove(file); var index = this.files.indexOf(file)
}, if (index != -1) {
}, this.files.splice(index, 1);
events: {
addFileUpload(file, component) {
console.log('addFileUpload');
if (this.auto) {
component.active = true;
} }
}, },
fileUploadProgress(file, component) { },
console.log('fileUploadProgress ' + file.progress);
},
afterFileUpload(file, component) {
console.log('afterFileUpload');
},
beforeFileUpload(file, component) {
console.log('beforeFileUpload');
},
}
}); });

@ -2,19 +2,24 @@ var path = require('path')
var webpack = require('webpack') var webpack = require('webpack')
module.exports = { module.exports = {
entry: { entry: {
example: ['vue', './src/example.js'], example: ['./src/example.js'],
}, },
output: {
path: './dist',
publicPath: '/dist/',
filename: "[name].js",
},
output: {
path: './dist',
publicPath: '/dist/',
filename: "[name].js",
},
resolveLoader: { resolve: {
root: path.join(__dirname, 'node_modules'), root: path.join(__dirname, 'node_modules'),
alias: {
},
extensions: ['', '.js', '.vue', '.json'],
}, },
module: { module: {
loaders: [ loaders: [
{ {
@ -44,6 +49,12 @@ module.exports = {
} }
] ]
}, },
babel: {
presets: ['es2015', 'stage-0'],
plugins: ['transform-runtime', 'transform-vue-jsx'],
},
devServer: { devServer: {
historyApiFallback: true, historyApiFallback: true,
noInfo: true noInfo: true

Loading…
Cancel
Save