接上回《Plupload插件》,已经尝试将Plupload插件引入到HTML页面中,并进行参数配置,然后联合后端接口进行调试,完成了文件上传的工作。但是在Vue项目的开发中,我们更想将它封装成一个可复用的Vue组件,在使用的时候,只需要快捷引入,并配置参数与回调函数即可。
有兴趣的小伙伴可以也可点击此处,从Gitee上直接拉取项目源码运行。
调用方式
使用自定义的FileUploader组件时,调用方式如下。
<template>
<div class="home">
<!-- 文件上传组件 -->
<FileUploader
:url="url"
:params="params"
:mime_types="mimeTypes"
:max_file_size="maxFileSizeLimit"
@whenUpload="whenUpload"
@successCallBackLater="uploadCallBack"
@errorCallBackLater="errorCallBack"
/>
</div>
</template>
<script>
// @ is an alias to /src
// import HelloWorld from '@/components/HelloWorld.vue'
//导出文件上传组件
import FileUploader from "@/components/fileTools/FileUploader";
export default {
name: "home",
components: {
//注册组件
FileUploader,
},
data() {
return {
//这里是后端接口-可参考前一篇文章的示例代码
url: "http://localhost:8099/sci_web/upload",
//params参数对应后端编写的JavaBean/pojo类对象+属性值
params: {
username: "小张",
password: "258596",
role: 0,
state: 1,
},
mimeTypes: "image/*,audio/*,video/*,text/*,application/zip", //MIME类型-默认支持文本/图像/音视频/二进制压缩包
maxFileSizeLimit: 1024,
};
},
methods: {
//以下三个函数是暴露出来的回调函数接口
whenUpload(msg) {
console.log(msg);
},
uploadCallBack(uploader, file, responseObject) {
console.log(responseObject);
},
errorCallBack(uploader, error) {
console.log(error);
},
},
};
</script>
组件封装源码
FileUploader组件简介
组件名称:FileUploader.vue,支持:多文件选择、已选文件移除、多文件分块上传,此外,也暴露出了如下3个接口,
①whenUpload:执行文件上传操作时的回调函数
②successCallBackLater:文件上传成功时的回调函数
③errorCallBackLater:文件上传发生错误时的回调函数。
上图是组件示例(有点丑,样式可根据自己需要进行调整哈)。
FileUploader组件源码
以下部分是我在Plupload插件基础上封装好的Vue组件,源码如下。
<template>
<div class="wrapper">
<br />
<div class="btns_group">
<div class="select_file btn default" id="browse">选择文件</div>
<div
class="upload_btn btn success"
id="start-upload"
@click="startUpload"
>
开始上传
</div>
<div class="upload_btn btn success" id="start-upload" @click="clearFiles">
重新选择
</div>
</div>
<!-- <div class="horizen_splitLine"></div> -->
<div class="selectedFiles">
<!-- 动态渲染文件列表 -->
<div class="file_row" v-for="(item, index) in fileList" :key="index">
<img :src="require('@/assets/icons/file-icon.png')" />
<span>{{ item.name }}</span>
<span>{{ (item.size / 1024).toFixed(2) + "MB" }}</span>
<span>{{ item.percent != 0 ? item.percent + "%" : "" }}</span>
</div>
</div>
</div>
</template>
<script>
//导入plupload插件库
import plupload from "plupload";
export default {
name:"FileUploader",
props: [
"url", //文件上传请求地址
"mime_types", //要上传的文件类型
"max_file_size", //单个文件大小上限
"params", //除文件之外的附加参数
],
data() {
return {
pluploadObj: undefined, //plupload文件上传插件对象
fileList: [], //已选择的文件列表
};
},
methods: {
/**
* 执行文件上传操作
*/
startUpload() {
this.pluploadObj && this.pluploadObj.files.length > 0
? this.pluploadObj.start()
: this.$emit("whenUpload", { msg: "plupload happened error!" });
},
/**
* 重新选择文件-清空文件列表
*/
clearFiles() {
if (this.pluploadObj && this.fileList && this.fileList.length > 0) {
//清空文件列表
let _that = this;
this.fileList.some(function (value, index, array) {
_that.pluploadObj.removeFile(value);
});
this.fileList.splice(0, this.fileList.length);
}
},
/**
* 文件上传成功时的回调函数
*
*/
callBack(uploader, file, responseObject) {
//自定义事件-文件上传成功之后-接收服务器端返回值
this.$emit("successCallBackLater", uploader, file, responseObject);
},
errorCallBack(uploader, error) {
//自定义事件-文件上传发生错误时-自定义处理方式
this.$emit("errorCallBackLater", uploader, error);
},
},
mounted() {
let _that = this;
//plupload插件参数配置
let pluploadConfig = {
browse_button: "browse", //文件上传按钮
url: this.$props.url, //文件请求接口
filters: {
//文件类型过滤器-默认支持所有文件类型
mime_types: this.$props.mime_types
? this.$props.mime_types
: "image/*,audio/*,video/*,text/*,application/zip",
//单个文件大小定义
max_file_size: this.$props.max_file_size
? this.$props.max_file_size + "mb"
: "0", //默认0-无上限
//防止文件重复选择
prevent_duplicates: true, //default-false
multipart: true, //default -true ,是否将文件作为 multipart/form-data (default) 或者binary stream上传
drop_element: "browse", //拖拽方式选择文件
multi_selection: true, //开启多文件上传
unique_names: true, //为每个文件自动生成唯一名称-作为额外的参数post到服务器端,参数明为name,值为生成的文件名
chunk_size: "1Mb", //文件分块大小
},
init: {
//文件上传之前的回调函数
BeforeUpload: function (up, files) {
up.setOption("multipart_params", _that.$props.params);
},
//添加文件时的回调函数
FilesAdded: function (up, files) {
// var html = "";
plupload.each(files, function (file) {
//记录当前选中的文件-Vue组件自动刷新-无需定制
_that.fileList.push(file);
});
},
//文件上传时的进度条绑定
UploadProgress: function (up, file) {
//已经封装到Vue组件中-自动刷新-无须定制
},
/**
* uploader为当前的plupload实例对象,file为触发此事件的文件对象,responseObject为服务器返回的信息对象,它有以下3个属性:
* response:服务器返回的文本
* responseHeaders:服务器返回的头信息
* status:服务器返回的http状态码,比如200
*/
FileUploaded: function (uploader, file, responseObject) {
//回调函数处理
_that.callBack(uploader, file, responseObject);
},
//错误处理回调函数
Error: function (up, err) {
//回调函数处理
_that.errorCallBack(up, err);
},
},
};
//初始化plupload插件
this.pluploadObj = new plupload.Uploader(pluploadConfig);
//调用初始化方法
this.pluploadObj.init();
},
};
</script>
<style scoped>
.wrapper {
position: absolute;
/* top: 50%;
left: 50%;
transform: translate(-50%, -50%); */
width: 350px;
border: 1px solid #ccc;
border-radius: 5%;
background-color: #ffffff;
}
.default {
background-color: #409eff;
}
.success {
background-color: #67c23a;
}
.btn {
color: #ffffff;
padding: 5px;
border: 1px solid #ccc;
border-radius: 10%;
}
.btns_group {
display: flex;
flex-direction: row;
justify-content: space-around;
}
div {
cursor: pointer;
}
/* 文件上传列表样式 */
.filelist {
list-style: none;
}
.selectedFiles {
margin: 15px 5px;
border-top: 1px solid #ccc;
}
.selectedFiles .file_row {
padding: 10px 5px;
}
.selectedFiles img {
margin-left: 5px;
}
.selectedFiles span {
margin: 5px 10px;
}
</style>