跳到主要内容

编程日志(08)—vue实现plupload分片上传

· 阅读需 5 分钟
<!-- plupload封装 -->
<template>
<div class="supload">
<div class="clearfix list-picture" v-if="fileList.length>0&&listType=='picture'">
<div v-for="ff,index in fileList" class="pic-bx small">
<img :src="ff.showUrl">
<div class="cl-bx">
<i class="el-icon-close" @click="deleteFile(ff,index)"></i>
</div>
</div>
</div>
<div class="plupload clearfix" v-show="fileList.length<maxFile">
<template v-if="listType=='text'">
<div class="text_trigger">
<div :id="trigger_id" >
<i class="el-icon-document" ></i>
<span>{{triggerText}}(小于{{maxSize}}Mb)</span>
</div>
</div>
</template>
<template v-if="listType=='picture'">
<div class="fm-up" :id="trigger_id">
<div class="cc">
<i class="el-icon-circle-plus-outline"></i>
<p>点击选择</p>
<span>支持jpg/png格式</span>
<span>560px×400px</span>

</div>
</div>
</template>
</div>
<div class="pgs" v-if="progress>0&&listType=='text'">
<el-progress :text-inside="true" :stroke-width="20" :percentage="progress" status="success"></el-progress>
</div>

<div class="list-text" v-if="listType=='text'">
<template v-for="ff,index in fileList">
<div class="clearfix item-text">
<!-- <div class="progress" :style="{'width':ff.progress+'%'}"></div> -->
<div class="title">{{ff.name}}</div>
<div class="close" @click="deleteFile(ff,index)">删除</div>
</div>

</template>
</div>

</div>
</template>

<script>
/**
* 强制multi_selection为false使其只能逐个上传
*
*/
/**
* tip:
* 为了操作方便fileList以数组形式传入props,直接操作fileList可以实现数据双向绑定
* 并不建议这样去做,父子组件之间尽量保持单向数据流
* 因此可以暂不向外提供文件删除上传的回调入口
*/
/*
xlsx等文档可以在拓展过滤为zip的情况下可选的bug是因为xlsx本质是个压缩包,将xlsx拓展名改成zip再看看
*/
import plupload from 'plupload'
import {guid,getExtName} from '../../lib/util.js'

import config from '../../config/config.js'
export default {
data() {
return {
trigger_id:null, //触发按钮的ID属性
plup:null, // plupload实例对象
progress: 0, // 单文件上传进度
option: null
};
},
props: {
accept: {
type: String,
default: 'image/png,image/jpeg,audio/mp3'
},
// 支持的拓展名以逗号隔开jpg,gif,png,bmp,mp4
extensions:{
type: String,
default: 'mp4'
},
maxFile: {
type: Number,
default: 1
},
maxSize: {
type: Number,
default: 512 //mb
},
// 文件列表
fileList: {
default(){
return []
}
},
// text,picture 以picture形式呈现时,如果超过可上传数量,上传界面将消失
listType:{
default: 'text'
},
params:{
type:Object,
required:true
},
triggerText:{
default:'选择文件'
}
},
computed:{

},
components: {

},

methods: {
transGetUrl(url) {
return config.imgHost + url
},


deleteFile(ff,index){
this.fileList.splice(index,1)
},

},
watch:{
extensions(ne,olg){
this.option.filters.mime_types=[{
title: 'files', extensions: ne
}]

this.plup.destroy()
this.plup = new plupload.Uploader(this.option);
this.plup.init()

}

},
mounted(){
const $this = this;
this.option = {
runtimes: 'html5,flash,silverlight,html4',
url: config.downloadHost+'upload/pluploadUpload',
//url: '/preschool/upload/pluploadUpload',
browse_button: this.trigger_id,
chunk_size: '2048kb',
multi_selection:false,
filters: {
mime_types: [{ title: 'files', extensions: this.extensions }],
max_file_size: this.maxSize+'mb',
prevent_duplicates: true
},
multipart:true,
multipart_params:this.params,
init: {
FilesAdded: function(up, files) {
up.start();
},
UploadProgress: function(up, file) {
$this.progress = file.percent;
},
BeforeUpload: function(up,file) {},
FileUploaded: function(uploader,file,res){
// response,responseHeaders,status
if (res.status==200){
let result = JSON.parse(res.response);
if (result.code==0){
setTimeout(function(){
$this.progress = 0;
$this.fileList.push({
name:file.name,
// url: result.data.replace(/(.*)(pluploadDir)/g,config.imgHost),
url: result.data,
showUrl: $this.transGetUrl(result.data),
type: getExtName(result.data)
});
},500);
}
} else {
}
},
Error:function(up,err){},
Refresh: function(up){},
Destroy(up){},
OptionChanged:function(up,option_name,new_value,old_value){}
// Error: this.error
}
}
this.plup = new plupload.Uploader(this.option);
this.plup.init();
},
beforeMount(){
this.trigger_id = guid();
}
};
/**
* 额外参数传递:
* 1.设置multipart为true
* 为true时将以multipart/form-data的形式来上传文件,为false时则以二进制的格式来上传文件。
* 2. 设置multipart_params:{userId:1024}
* 方式二
* 设置init的BeforeUpload(up,file){up.setOption("multipart_params",{userId:1024})}
* 也可以up.setOption({'multipart_params':{userId:1030}});这样可以方便设置多个参数
* 像 up.setOption({'multipart':true,'multipart_params':{userId:1032}})
* 在某些情况下可能更方便
*/
</script>

调用方式

<plup-vue :file-list="fileListForAttach" list-type="text" :params="extendParamsForUploadComponent" :extensions="format" :maxSize="1024">
</plup-vue>

CSS

/*上传组件*/
.supload{
line-height: 30px;
.pgs{
line-height:20px;width:600px;
}
.list-text{
line-height:20px;width:600px;
.item-text{
line-height: 30px;
height: 30px;
background: #ededed;
position: relative;
margin: 5px auto;
.progress{
position: absolute;
height: 100%;
width: 1%;
background: green;
top: 0;left: 0;
opacity: 0.2;
transition: width 0.5s;
-moz-transition: width 0.5s;
-webkit-transition: width 0.5s;
-o-transition: width 0.5s;

}
.title{
float: left;height: inherit;line-height: inherit;padding: 0 10px;
width: 500px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.close{
float: right;height: inherit;
line-height: inherit;padding: 0 10px;
cursor: pointer;
color:$colorRed
}
}
}
.list-picture {

.pic-bx{
float: left;
margin: 10px 10px 10px 0;
border:1px dashed #ededed;
img{width: 100%; }
position: relative;
}
.cl-bx{
width: 100%;height: 25px;background: rgba(1,1,1,0.5);
position: absolute;right: 0;top: 0;
text-align: right;
line-height: 25px;
i{
font-size: 15px;
color:#fff;
margin-right: 3px;
cursor: pointer;
}
}
.small{
width: 240px;height: 180px;overflow: hidden;
border-radius: 4px
}
}
.plupload{
.text_trigger{
display: inline-block;
position: relative;
color:$colorBlue;
cursor: pointer;
}

}

}
.fm-up{
width: 240px;height: 180px;
text-align: center;
cursor: pointer;
// border: 1px solid #03A9F4;
.cc{
height: 100px;width: 200px;
line-height: 20px;
margin: auto;
margin-top: 40px;
}
color:#dcdcdc;
border: 1px solid #dcdcdc;
i{font-size: 25px;}
border-radius: 4px;
p{line-height: 20px;}
span{font-size: 12px;line-height: 20px;}
}