@15013890200
2018-08-29T17:33:28.000000Z
字数 4927
阅读 703
vue
javascript
插件
文件上传功能是交互式网站必不可少的功能。一年前,笔者还是什么都不懂得小白(虽然现在懂得也很少)的时候,被这个功能折磨了好一阵子。求助师兄师姐才勉强会用封装好的插件。
最近,抽空写了个简单的文件上传插件,下面将介绍此插件的特点。1、该插件严格上来说,并不能算真正的文件上传插件。我只是利用该插件获取到自己选择的文件的信息,包括文件对象和文件base64编码,然后返回。至于后来怎样上传、何时上传就因人而异。
2、该插件支持的配置:是否支持多选、上传文件的大致类型、上传文件的后缀、上传文件的字节大小、上传文件的宽高、是否严格限制上传文件的宽高。
3、由于该插件并不将文件直接上传到服务器。因此给用户带来撤回选择文件的功能,减轻服务器的压力。
4、选择的文件展示方面,支持图片缩略图。定制化excel、word、ppt、txt、html、pdf、rar、video文件图标,以及默认文件图标。
源代码
<template>
<div class="j_div_upload clearfix">
<input type="file" class="j_ip_hide" @change="getSelect">
<div class="j_div_imgs">
<div class="j_imgs_div">
<div v-for="(img,index) in imgs" class="j_div_item">
<img :src="img.icon?img.icon:img.base64" class="j_img_item">
<span :title="img.name">{{img.name}}</span>
<i class="j_i_close" @click="deleteItem(index)"></i>
</div>
</div>
<div class="j_div_add" @click="select"></div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
export default{
name: 'myupload',
data(){
return {
imgs: [],//存放选中的文件对象
multiple: false,//标志是否支持多文件上传
type: '',//文件的大致类型。目前最好传入image或者video
size: null,//允许文件的字节大小
format: [],//允许文件的具体后缀
width: null,//图片的宽度
height: null,//图片的高度
strict: false,//图片长宽是否严格限制在标注尺寸
icon: require('./img/file.png')
}
},
props: {
uploadObj: {
type: Object,
default: null
}
},
methods: {
select: function(){
/** 触发文件上传操作 */
this.$el.firstChild.click();
},
getSelect: function(event){
/** 获取文件对象并进行处理和控制 */
if(!event.target.files || !event.target.files[0])return;
let _this = this;
let file = event.target.files[0];
if(this.type && file.type.indexOf(this.type) === -1){
this.Layer.alert('上传文件类型错误,应该上传 '+this.type+' 类型');
return;
}
if(this.format && this.format.length){
let file_type = file.name.split('.').pop(1).toLowerCase();
if(this.format.indexOf(file_type) === -1){
this.Layer.alert('上传文件后缀与指定后缀类型不符( '+this.format.join(',')+' )');
return;
}
}
if(this.size && file.size > this.size * 1024 * 1024){
this.Layer.alert('文件超过'+this.size+'M限制');
return;
}
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(evt){
if(file.type.indexOf('image') !== -1){
let image = new Image();
image.src = evt.target.result;
image.onload = function(){
let w = image.width;
let h = image.height;
if(_this.strict){
if(_this.width && _this.height && (w != _this.width || h != _this.height)){
_this.Layer.alert('图片的宽高不符合要求,宽必须为:'+_this.width+',高必须为:'+_this.height);
return;
}
}
else{
if(_this.width && _this.height && (w > _this.width || h > _this.height)){
_this.Layer.alert('图片的宽高不符合要求,宽不能大于:'+_this.width+',高不能大于:'+_this.height);
return;
}
}
if(_this.multiple){
_this.imgs.push({
name: file.name,
date: file.lastModified,
base64: evt.target.result,
file: file
});
}
else{
_this.imgs = [{
name: file.name,
date: file.lastModified,
base64: evt.target.result,
file: file
}];
}
}
}
else{
let file_tail = file.type.split('.').pop();
switch(file_tail){
case 'sheet': _this.icon = require('./img/excel.png');break;
case 'document': _this.icon = require('./img/word.png');break;
case 'presentation': _this.icon = require('./img/ppt.png');break;
default: _this.icon = require('./img/file.png');
}
if(file.type.indexOf('pdf') !== -1)_this.icon = require('./img/pdf.png');
if(file.type.indexOf('video') !== -1)_this.icon = require('./img/video.png');
if(file.type === 'text/plain')_this.icon = require('./img/txt.png');
if(file.type === 'text/html')_this.icon = require('./img/html.png');
if(!file.type && file.name.split('.').pop() == 'rar')_this.icon = require('./img/rar.png');
if(_this.multiple){
_this.imgs.push({
name: file.name,
date: file.lastModified,
base64: evt.target.result,
file: file,
icon: _this.icon
});
}
else{
_this.imgs = [{
name: file.name,
date: file.lastModified,
base64: evt.target.result,
file: file,
icon: _this.icon
}];
}
}
}
setTimeout(function(){
event.target.files = null;
},500);
},
deleteItem: function(idx){
/** 删除已选的文件 */
this.imgs.splice(idx,1);
}
},
beforeMount(){
for(let i in this.uploadObj){
if(i !== 'imgs'){
this.$data[i] = this.uploadObj[i];
}
}
console.log(this.uploadObj);
},
watch: {
'imgs': function(){
let files = {base64: [],files: []};
this.imgs.forEach(function(item){
files.base64.push(item.base64);
files.files.push(item.file);
});
this.$emit('callback',files);
}
}
}
</script>
<style scoped>
*{padding: 0;margin: 0;}
.j_div_upload{margin-bottom:10px;}
.j_ip_hide{width: 0;height: 0;opacity: 0;overflow: hidden;border:none;outline: none;margin: 0;padding: 0;}
.j_div_add{width: 80px;height: 80px;background:url(img/add-pic.png) no-repeat;background-size: 80px 80px;margin: 0;float: left;cursor: pointer;}
.j_imgs_div,.j_div_imgs{float:left;}
.j_div_item{width:80px;height:100px;float:left;margin-right:10px;text-align:center;position:relative;}
.j_img_item{width:80px;height:80px;background-color:#ddd;}
.j_div_item span{color:#bbb;font-size:12px;float:left;display:inline-block;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
.j_i_close{background:url(img/close.png) no-repeat;display:inline-block;width:16px;height:16px;position:absolute;top:-5px;right:-5px;cursor:pointer;}
</style>
插件注册及引用省略
参数配置
参数名 | 参数意义 | 参数类型 | 默认值 | 是否必须 |
---|---|---|---|---|
multiple | 是否支持多文件上传 | Boolean | false | 否 |
type | 支持文件大致格式(最好传image或video) | string | 无 | 否 |
size | 支持文件字节大小 | number | null | 否 |
format | 允许的文件后缀 | array | null | 否 |
width | 图片的宽度限制 | number | null | 否 |
height | 图片的高度限制 | number | null | 否 |
strict | 是否严格限制图片宽高 | Boolean | false | 否 |
当strict参数为true时,会严格限制图片的宽高等于约定的尺寸,否则只控制图片的宽高小于约定的尺寸即可。
效果图