v0.2.0, Add Put method, Upload speed

1.0
git 10 years ago
parent 334ec1a2d0
commit 9aed68961e

@ -15,7 +15,7 @@
var FileUpload = require('vue-upload-component');
new Vue({
template: '<file-upload action="/"></file-upload>',
template: '<file-upload post-action="/post.method" put-action="/put.method"></file-upload>',
components: {
FileUpload: FileUpload
}
@ -27,7 +27,7 @@
```js
import FileUpload from 'vue-upload-component'
new Vue({
template: '<file-upload action="/"></file-upload>',
template: '<file-upload post-action="/post.method" put-action="/put.method"></file-upload>',
components: {
FileUpload
}
@ -94,16 +94,16 @@ npm run build
{
files: [
{
id: 'String',
id: 'String', // Read only
name: 'filename String',
size: 'filesize Number',
progress: 'progress String',
progress: 'progress String', // Read only
speed: "Speed Number", // Read only
active: 'active Boolean',
error: 'error String',
errno: 'errno String',
success: 'success Boolean',
data: 'Response data Object or String',
success: 'success Boolean', // Read only
data: 'Response data Object or String', // Read only
request: {
headers: {
"X-Csrf-Token": "xxxx",
@ -112,10 +112,10 @@ npm run build
"_csrf_token": "xxxxxx",
},
},
}
],
// Global
request: {
headers: {
@ -125,11 +125,41 @@ npm run build
"_csrf_token": "xxxxxx",
},
},
active: false,
uploaded: true, // Read only
dropActive: false, // Read only
}
```
### Props
``` html
<file-upload :title="Add upload files" :name="file" :action="./upload.php" :accept="accept" :multiple="multiple" :size="size" :timeout="3600000"></file-upload>
<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="multiple" :size="size" :timeout="3600000"></file-upload>
```
```
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"
post-action="./post.method"
put-action="./put.method"
accept="accept"
multiple="multiple"
size="max Size"
timeout="3600000"
```

1545
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

@ -5,12 +5,28 @@
<title>vue-upload-component</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.24/vue.min.js"></script>
<style type="text/css">
#app {
position: relative;
}
.file-uploads-label {
display: block;
}
.file-uploads-label span{
display: block;
font-size: 18px;
padding: 1em;
font-weight: bold;
border: 1px solid #888;
}
.drop-active {
top: 0;
bottom: 0;
right: 0;
left: 0;
position: absolute;
opacity: .4;
background: #000;
}
</style>
</head>
<body>
@ -19,9 +35,11 @@
<thead>
<tr>
<th>Index</th>
<th>ID</th>
<th>Name</th>
<th>Size</th>
<th>Progress</th>
<th>Speed</th>
<th>Active</th>
<th>Error</th>
<th>Errno</th>
@ -33,9 +51,11 @@
<tbody>
<tr v-for="file in $refs.upload.files">
<td>{{$index}}</td>
<td>{{file.id}}</td>
<td>{{file.name}}</td>
<td>{{file.size}}</td>
<td>{{file.size | formatSize}}</td>
<td>{{file.progress}}</td>
<td>{{file.speed | formatSize}}</td>
<td>{{file.active}}</td>
<td>{{file.error}}</td>
<td>{{file.errno}}</td>
@ -51,27 +71,54 @@
<tbody>
<tr>
<td>
<file-upload title="Add upload files" name="file" action="./upload.php" :accept="accept" :multiple="multiple ? 'true' : null" :size="size" v-ref:upload></file-upload>
<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 ? 'true' : null" :size="size" v-ref:upload :drop="drop"></file-upload>
</td>
<td>
<button v-if="$refs.upload && $refs.upload.active" type="submit" @click.prevent="$refs.upload.active = !$refs.upload.active">Stop upload</button>
<button v-else type="submit" @click.prevent="$refs.upload.active = !$refs.upload.active">Start upload</button>
</td>
<td>
<label>
Accept: <input type="text" v-model="accept">
</label>
</td>
<td>
<label>
Extensions: <input type="text" v-model="extensions">
</label>
</td>
<td>
<label>
Drop: <input type="checkbox" id="checkbox" v-model="drop">
</label>
</td>
<td>
<label>
Max file size: <input type="text" v-model="size">
</label>
</td>
<td>
<label>
Multiple: <input type="checkbox" id="checkbox" v-model="multiple">
</label>
</td>
</tr>
<tr>
<td>
Active: {{$refs.upload.active}}
</td>
<td>
Status: Active: {{$refs.upload.active}}, Uploaded: {{$refs.upload.uploaded}}
Uploaded: {{$refs.upload.uploaded}}
</td>
<td>
Drop active: {{$refs.upload.dropActive}}
</td>
</tr>
</tbody>
</table>
<div v-show="$refs.upload.dropActive" class="drop-active">
Drop ing
</div>
</div>
<script src="./dist/example.js"></script>
</body>

@ -1,7 +1,7 @@
{
"name": "vue-upload-component",
"description": "Vue.js file upload component, Support for multiple file uploads, progress, html5, html4, support ie9",
"version": "0.1.11",
"version": "0.2.0",
"author": "LianYue",
"scripts": {
"dev": "webpack-dev-server --inline --hot",

@ -43,6 +43,11 @@
</style>
<script>
const createId = function() {
return Math.random().toString(36).substr(2);
}
export default {
props: {
title: {
@ -51,14 +56,18 @@ export default {
},
name: {
type: String,
required: true
default: 'file',
},
drop: {
default: false,
},
id: {
extensions: {
},
postAction: {
type: String,
},
action: {
putAction: {
type: String,
required: true
},
accept: {
type:String,
@ -91,6 +100,8 @@ export default {
files: [],
active: false,
uploaded: true,
dropActive: false,
dropElement: false,
request: {
data: {},
headers: {},
@ -98,6 +109,10 @@ export default {
}
},
created() {
this._drop(this.drop);
},
init() {
var input = document.createElement('input');
input.type = 'file';
@ -107,15 +122,20 @@ export default {
this.$mode = 'html4';
}
this._index = 0;
this._dropActive = 0;
this._files = {};
},
beforeDestroy() {
this.active = false;
this.files = [];
},
watch: {
drop(value) {
this._drop(value);
},
files(files) {
var ids = [];
for (var i = 0; i < files.length; i++) {
@ -162,6 +182,78 @@ export default {
},
methods: {
_drop(value) {
if (this.dropElement) {
try {
if (this.$mode === 'html5') {
window.document.removeEventListener('dragenter', this._onDragenter, false);
window.document.removeEventListener('dragleave', this._onDragleave, false);
this.dropElement.removeEventListener('dragover', this._onDragover, false);
this.dropElement.removeEventListener('drop', this._onDrop, false);
}
} catch (e) {
}
}
if (!value) {
this.dropElement = false;
return;
}
if (typeof value == 'string') {
this.dropElement = document.querySelector(value);
} else if (typeof value == 'boolean') {
this.dropElement = this.$parent.$el;
} else {
this.dropElement = this.drop;
}
if (this.$mode === 'html5') {
window.document.addEventListener('dragenter', this._onDragenter, false);
window.document.addEventListener('dragleave', this._onDragleave, false);
this.dropElement.addEventListener('dragover', this._onDragover, false);
this.dropElement.addEventListener('drop', this._onDrop, false);
}
},
_onDragenter(e) {
this._dropActive++;
this.dropActive = !!this._dropActive;
e.preventDefault();
},
_onDragleave(e) {
e.preventDefault();
this._dropActive--;
if (e.target.nodeName == 'HTML' || (e.screenX == 0 && e.screenY == 0)) {
this.dropActive = !!this._dropActive;
}
},
_onDragover(e) {
e.preventDefault();
},
_onDrop(e) {
this._dropActive = 0;
this.dropActive = false;
e.preventDefault();
if (e.dataTransfer.files.length) {
for (var i = 0; i < e.dataTransfer.files.length; i++) {
var file = e.dataTransfer.files[i];
var id = createId();
var value = {id: id, size:file.size, name: file.name, progress: '0.00', speed: 0, active: false, error: '', errno: '', success: false, data: {}, request: {headers:{}, data:{}}};
this._files[id] = {file: file};
var len;
if (this.multiple) {
len = this.files.push(value);
} else {
this.files = [value];
len = 1;
}
this._files[id]._file = this.files[len-1];
this.$dispatch('addFileUpload', this.files[len-1], this);
}
}
},
_addFileUploads(el) {
var Component = this.$options.components.inputFile;
new Component({
@ -174,8 +266,8 @@ export default {
if (el.files) {
for (var i = 0; i < el.files.length; i++) {
var file = el.files[i];
var id = 'upload-file-' + Math.random().toString(36).substr(2);
var value = {id: id, size:file.size, name: file.name, progress: '0.00', active: false, error: '', errno: '', success: false, data: {}, request: {headers:{}, data:{}}};
var id = createId();
var value = {id: id, size:file.size, name: file.name, progress: '0.00', speed: 0, active: false, error: '', errno: '', success: false, data: {}, request: {headers:{}, data:{}}};
this._files[id] = {el:el, file: file};
var len;
@ -189,8 +281,8 @@ export default {
this.$dispatch('addFileUpload', this.files[len-1], this);
}
} else {
var id = 'upload-file-' + Math.random().toString(36).substr(2);
var value = {id: id, size: -1, name: el.value.replace(/^.*?([^\/\\\r\n]+)$/, '$1'), progress: '0.00', active: false, error: '', errno: '', success: false, data: {}, request: {headers:{}, data:{}}};
var id = createId();
var value = {id: id, size: -1, name: el.value.replace(/^.*?([^\/\\\r\n]+)$/, '$1'), progress: '0.00', speed:0, active: false, error: '', errno: '', success: false, data: {}, request: {headers:{}, data:{}}};
this._files[id] = {el:el};
var len;
if (this.multiple) {
@ -220,10 +312,46 @@ export default {
continue;
}
if (this.extensions.length || typeof this.extensions.length == 'undefined') {
var extensions = this.extensions;
if (typeof extensions == 'object' && RegExp instanceof extensions) {
} else {
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) {
file.error = 'Extension';
file.errno = 'extension';
continue;
}
}
if (this.$mode == 'html5') {
if (this.putAction || file.putAction) {
this._fileUploadPut(file);
} else if (this.postAction || file.postAction) {
this._fileUploadHtml5(file);
} else {
file.error = 'Not Support';
file.errno = 'not_support';
continue;
}
} else {
if (this.postAction || file.postAction) {
this._fileUploadHtml4(file);
} else {
file.error = 'Not Support';
file.errno = 'not_support';
continue;
}
}
return;
}
@ -231,24 +359,12 @@ export default {
this.uploaded = true;
},
_fileUploadHtml5(file) {
_fileUploadXhr(xhr, file, data) {
var _self = this;
var file2 = this._files[file.id];
var fileUploads = false;
var form = new window.FormData();
form.append(this.name, file2.file);
for (var key in this.request.data) {
form.append(key, this.request.data[key]);
}
for (var key in file.request.data) {
form.append(key, file.request.data[key]);
}
var xhr = new XMLHttpRequest();
var speedTime = 0;
var speedLoaded = 0;
xhr.upload.onprogress = function(e) {
if (file.removed) {
xhr.abort();
@ -260,6 +376,12 @@ export default {
}
if (e.lengthComputable) {
file.progress = (e.loaded / e.total * 100).toFixed(2);
var speedTime2 = Math.round(Date.now() / 1000);
if (speedTime2 != speedTime) {
file.speed = e.loaded - speedLoaded;
speedLoaded = e.loaded;
speedTime = speedTime2;
}
}
_self.$dispatch('fileUploadProgress', file, _self);
};
@ -329,23 +451,28 @@ export default {
xhr.timeout = this.timeout;
}
xhr.open('POST', this.action);
xhr.onload = callback;
xhr.onerror = callback;
xhr.onabort = callback;
xhr.ontimeout = callback;
if (this.timeout) {
xhr.timeout = this.timeout;
}
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
for (var key in this.request.headers) {
xhr.setRequestHeader(key, this.request.headers[key]);
}
for (var key in file.request.headers) {
xhr.setRequestHeader(key, file.request.headers[key]);
}
xhr.send(form);
xhr.send(data);
file.active = true;
file2.xhr = xhr;
var interval = setInterval(function() {
if (!_self.active || !file.active || file.success || file.errno) {
clearInterval(interval);
@ -353,9 +480,42 @@ export default {
xhr.abort();
}
}
}, 50);
}, 100);
this.$dispatch('beforeFileUpload', file, this);
},
_fileUploadPut(file) {
var _self = this;
var querys = Vue.util.extend(Vue.util.extend({}, this.request.data), file.request.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 ? '?' + queryArray.join('&') : '';
var xhr = new XMLHttpRequest();
xhr.open('PUT', (file.putAction || this.putAction) + queryString);
this._fileUploadXhr(xhr, file, this._files[file.id].file);
},
_fileUploadHtml5(file) {
var form = new window.FormData();
form.append(this.name, this._files[file.id].file);
for (var key in this.request.data) {
form.append(key, this.request.data[key]);
}
for (var key in file.request.data) {
form.append(key, file.request.data[key]);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', file.postAction || this.postAction);
this._fileUploadXhr(xhr, file, form);
},
_fileUploadHtml4(file) {
var _self = this;
@ -384,7 +544,7 @@ export default {
var form = document.createElement('form');
form.action = this.action;
form.action = file.postAction || this.postAction;
form.name = 'upload-form-' + file.id;
form.setAttribute('method', 'POST');
form.setAttribute('target', 'upload-iframe-' + file.id);

@ -2,6 +2,20 @@
import FileUpload from './FileUpload.vue';
Vue.filter('formatSize', function(size) {
if (size > 1024 * 1024 * 1024 * 1024) {
return (size / 1024 / 1024 / 1024 / 1024).toFixed(2) + ' TB';
} else if (size > 1024 * 1024 * 1024) {
return (size / 1024 / 1024 / 1024).toFixed(2) + ' GB';
} else if (size > 1024 * 1024) {
return (size / 1024 / 1024).toFixed(2) + ' MB';
} else if (size > 1024) {
return (size / 1024).toFixed(2) + ' KB';
}
return size.toString() + ' B';
});
new Vue({
el:'#app',
components: {
@ -11,6 +25,10 @@ new Vue({
accept: 'image/*',
size: 1024 * 1024 * 10,
multiple: true,
extensions: 'gif,jpg,png',
// extensions: ['gif','jpg','png'],
// extensions: /\.(gif|png|jpg)$/i,
drop: true,
},
compiled: function() {
this.$refs.upload.request = {

Loading…
Cancel
Save