最近项目中需要用到百度的webuploader大文件的分片上传,对接后端的fastdfs,于是着手写了这个文件上传的小插件,步骤很简单,但是其中猜到的坑也不少,本文主要介绍了vue webuploader 文件上传组件开发,小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助到大家。
详细如下:
一、封装组件
引入百度提供的webuploader.js、uploader.swf
css样式就直接写在组件里面了
<template>
<p>
<p id="list" class="uploader-list"></p>
<p id="wrapper">
<p class="uploader-container">
<p :id="id" limitsize="1" :ext="ext"></p>
<el-button style="margin-bottom:10px;float:left;" size="small" :loading="uploadloading" type="success" @click="start">上传到服务器</el-button>
<el-button style="margin-left: 20px;margin-bottom:10px;float:left;" :disabled="stopbtn" size="small" type="danger" @click="stop">暂停上传</el-button>
</p>
</p>
<p class="el-upload__tip">{{tip}}</p>
<p class="file-list">
<ul class="el-upload-list el-upload-list--text">
<li v-for="file in filelist" :class="['el-upload-list__item', 'is-' + file.status]" :key="file">
<a class="el-upload-list__item-name">
<i class="el-icon-document"></i>{{file.name}}
</a>
<label class="el-upload-list__item-status-label">
<i :class="{'el-icon-upload-success': true,'el-icon-circle-check': listtype === 'text',
'el-icon-check': ['picture-card', 'picture'].indexof(listtype) > -1}"></i>
</label>
<i class="el-icon-close" @click="removefile(file)"></i>
<el-progress
v-if="file.status === 'uploading'"
:type="listtype === 'picture-card' ? 'circle' : 'line'"
:stroke-width="listtype === 'picture-card' ? 6 : 2"
:percentage="file.percentage">
</el-progress>
</li>
</ul>
</p>
</p>
</template>
<script>
import '../js/jquery.js'
import '../js/webuploader.js'
import { base64 } from 'js-base64'
import cryptojs from 'crypto-js';
export default{
name: 'fileupload',
props: {
id: {
type: string,
default: function(){
return "filepicker";
}
},
//上传提示
tip: {
type: string,
default: function(){
return "";
}
},
//文件后缀名限制
ext: {
type: string,
default: function(){
return "jpg,jpeg,png,pdf,mp4,avi.mp3";
}
},
//分片大小设置
chunksize: {
type: number,
default: function(){
return 2097152;
}
},
//分片上传重试次数
chunkretry: {
type: number,
default: function(){
return 1;
}
},
//是否自动上传
auto: {
type: boolean,
default: function(){
return false;
}
},
//上传文件大小限制
sizelimit: {
type: number,
default: function(){
return 209715200;
}
},
//上传文件数量限制
countlimit: {
type: number,
default: function(){
return 5;
}
}
},
data(){
return{
appid: appconfig.appid,
securitykey: appconfig.securitykey,
checkurl: appconfig.checkurl,
uploadurl: appconfig.uploadurl,
mergeurl: appconfig.mergeurl,
previewname: '选择文件',
wul_filemd5: '',
wul_size: 0,
wul_filename: '',
wul_chunk: 0,
wul_uploader: '',
filelist: [],
listtype: 'text',
percentage: 0,
fileobject: {
uid: '',
name: '',
ext: '',
type: '',
status: '',
percentage: 0,
url: ''
},
uploadloading: false,
stopbtn: true
}
},
methods: {
/**
* 获取当前上传列表中的文件
* @returns {array|*}
*/
getfilelist: function(){
return this.filelist;
},
//绑定事件
wul_init: function() {
//提示只能选择一个文件
this.wul_uploader.on('filesqueued', function (files) {
if (files.length > 1) {
this.$message({
message: '请选择一张图片',
type: 'error'
});
for (var i = 0; i < files.length; i++) {
this.wul_uploader.cancelfile(files[i]);
}
this.wul_uploader.reset();
this.wul_filemd5 = "";
this.wul_size = 0;
this.wul_filename = "";
this.wul_chunk = 0; //当前切片数
}else{
if( this.filelist.length == this.countlimit ){
this.$message({
message: '已经达到上传文件限制数量',
type: 'error'
});
}else{
//此时往需要上传的文件列表中添加文件
let file = {
uid: date.now() + this.tempindex++,
name: files[0].name,
type: files[0].type,
ext: files[0].ext,
status: "ready",
percentage: 0
}
this.fileobject = file;
this.filelist.push(this.fileobject);
}
}
}.bind(this));
//文件校验格式和大小
this.wul_uploader.on('error', function (type) {
debugger
if (type == 'q_exceed_size_limit') {
this.$message({
message: '文件超过指定大小',
type: 'error'
});
}
if (type == 'q_type_denied') {
this.$message({
message: '文件格式错误,请选择文件',
type: 'error'
});
}
if (type == 'f_exceed_size') {
this.$message({
message: "文件超过" + this.sizelimit / 1024 / 1024 + "m",
type: 'error'
});
}
}.bind(this));
//上传进度
this.wul_uploader.on('uploadprogress', function (file, percentage) {
this.percentage = percentage * 100;
this.fileobject.status = "uploading";
this.fileobject.percentage = this.percentage;
console.log(this.fileobject.percentage);
}.bind(this));
//每次切片上传完成之后的判断
this.wul_uploader.on('uploadaccept', function (object, ret) {
if (ret.responsecode != 0) {
this.wul_uploader.cancelfile(this.wul_uploader.getfiles()[0].id);
}
});
this.wul_uploader.on('uploadbeforesend', function(object, data, headers) {
console.log(data);
});
},
option: function(key, val) {
this.wul_uploader.option(key, val);
var options = this.wul_uploader.options;
this.wul_uploader.destroy(); //注销uploader
this.wul_uploader = webuploader.create(options);
this.wul_init();
},
start: function(){
if(this.wul_uploader.getfiles()[0] != null) {
this.wul_uploader.upload(this.wul_uploader.getfiles()[0].id);
this.uploadloading = true;
this.stopbtn = false;
} else {
this.$message({
message: "请选择上传文件",
type: 'error'
});
}
},
stop: function(){
this.wul_uploader.cancelfile(this.wul_uploader.getfiles()[0].id);
},
removefile: function(file){
this.filelist.splice(this.filelist.indexof(file), 1);
},
change: function(){
this.option('accept', {
title: 'images',
extensions: 'gif,jpg,jpeg,bmp,png'
});
}
},
mounted(){
webuploader.uploader.register({
"before-send-file": "beforesendfile",
"before-send": "beforesend",
"after-send-file": "aftersendfile",
}, {
beforesendfile: function (file) {
var deferred = webuploader.deferred();
this.wul_uploader.md5file(file).then(function (val) {
this.wul_filemd5 = val;
this.wul_size = file.size;
this.wul_filename = file.name;
var timestamp = date.parse(new date()) / 1000;
var signparam = "{chunksize=" + this.chunksize + ", filemd5=" + this.wul_filemd5 + ", size=" + this.wul_size + ", timestamp=" + timestamp + "}";
var sign = base64.encode(cryptojs.hmacsha1(signparam, this.securitykey));
// 获取断点续传位置
jquery.ajax({
type: "post",
// 测试
url: this.checkurl,
data: {
// 文件大小
size: this.wul_size,
// 文件唯一标记
filemd5: this.wul_filemd5,
// 切片大小
chunksize: this.chunksize,
// 签名
sign: sign,
// 应用分配id
appid: this.appid,
// 当前时间戳
timestamp: timestamp
},
datatype: "json",
// 上传失败
error: function (xmlhttprequest, textstatus, errorthrown) {
this.$message({
message: "上传失败...",
type: 'error'
});
this.uploadloading = false;
this.stopbtn = true;
}.bind(this),
success: function (response) {
if (response.responsecode == 0) { // 切片获取成功
this.wul_chunk = response.chunk;
deferred.resolve();
} else { // 切片获取失败,请求成功
this.wul_uploader.cancelfile(file); //取消文件上传
this.$message({
message: "切片检查失败,请联系管理员",
type: 'error'
});
deferred.resolve();
this.uploadloading = false;
this.stopbtn = true;
}
}.bind(this)
});
return deferred.promise();
}.bind(this));
return deferred.promise();
}.bind(this),
beforesend: function (block) {
var deferred = webuploader.deferred();
if (block.chunk < this.wul_chunk) {
return deferred.reject();
}
this.wul_uploader.md5file(block.blob).then(function (chunkmd5) {
var timestamp = date.parse(new date()) / 1000;
var signparam = '{chunk=' + block.chunk + ', chunkmd5=' + chunkmd5 + ', chunksize=' + this.chunksize + ', filemd5=' + this.wul_filemd5 + ', size=' + this.wul_size + ', timestamp=' + timestamp + '}';
var signtemp = cryptojs.hmacsha1(signparam, this.securitykey);
var sign = base64.encode(signtemp); //获取sign值
this.wul_uploader.options.formdata = {
'timestamp': timestamp,
'appid': this.appid,
'chunk': block.chunk,
'chunksize': this.chunksize,
'filemd5': this.wul_filemd5,
'chunkmd5': chunkmd5,
'size': this.wul_size,
'sign': sign
};
deferred.resolve();
}.bind(this))
return deferred.promise();
}.bind(this),
aftersendfile: function (file) {
var timestamp = date.parse(new date()) / 1000;
var signparam = "{chunksize=" + this.chunksize + ", filemd5=" + this.wul_filemd5 + ", filename=" + file.name + ", size=" + this.wul_size + ", timestamp=" + timestamp + "}";
var sign = base64.encode(cryptojs.hmacsha1(signparam, this.securitykey));
// 如果分块上传成功,则通知后台合并分块
jquery.ajax({
type: "post",
url: this.mergeurl,
data: {
appid: this.appid,
filemd5: this.wul_filemd5,
filename: file.name,
chunksize: this.chunksize,
sign: sign,
size: this.wul_size,
timestamp: timestamp
},
success: function (response) {
if (response.responsecode == 0) {
this.fileobject.status = "success";
this.fileobject.percentage = 100;
this.fileobject.url = response.filepath;
} else {
this.fileobject.status = "exception";
this.$message({
message: "上传失败,失败原因:" + response.responsemsg,
type: 'error'
});
}
this.uploadloading = false;
this.stopbtn = true;
this.wul_uploader.reset();
this.wul_filemd5 = "";
this.wul_size = 0;
this.wul_filename = "";
this.wul_chunk = 0; //当前切片数
}.bind(this)
});
}.bind(this)
});
this.wul_uploader = webuploader.create({
// swf文件路径
swf: '../js/uploader.swf',
// 文件接收服务端。
server: this.uploadurl,
// 定义选择按钮
pick: {
"id": "#" + this.id,
"innerhtml": this.previewname
},
// 自动上传
auto: this.auto,
// 禁止浏览器打开文件
disableglobaldnd: true,
// 添加截图功能
paste: '#wrapper',
// 定义拖动面板
dnd: '#wrapper',
// 分片上传
chunked: true,
// 分片大小为2m
chunksize: this.chunksize,
// 分片上传失败重试次数
chunkretry: this.chunkretry,
// 图片不做压缩
compress: false,
// 队列设置10个,为了选择多个文件的时候能提示
filenumlimit: 10,
// 提前准备好下一个文件
preparenextfile: true,
// 限制单个文件大小
filesinglesizelimit: this.sizelimit,
//线程数
threads : 1,
// 限制格式
accept: {
title: "access",
extensions: this.ext
}
});
this.wul_init();
}
}
</script>
<style>
/* ----------------reset css--------------------- */
html, body, p, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video, input {
margin: 0;
padding: 0;
border: none;
outline: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
html, body, form, fieldset, p, p, h1, h2, h3, h4, h5, h6 {
-webkit-text-size-adjust: none;
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
display: block;
}
body {
font-family: arial, sans-serif;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after {
content: '';
content: none;
}
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* ------------ */
#wrapper {
width: 100%;
margin: 0 auto;
height: 35px;
}
.img-preview {
width: 160px;
height: 90px;
margin-top: 1em;
border: 1px solid #ccc;
}
.cropper-wraper {
position: relative;
}
.upload-btn {
background: #ffffff;
border: 1px solid #cfcfcf;
color: #565656;
padding: 10px 18px;
display: inline-block;
border-radius: 3px;
margin-left: 10px;
cursor: pointer;
font-size: 14px;
position: absolute;
right: 1em;
bottom: 2em;
}
.upload-btn:hover {
background: #f0f0f0;
}
.uploader-container{
width: 100%;
font-size: 10px;
}
.webuploader-container {
position: relative;
width: 100px;
height: 21px;
float: left;
}
.webuploader-element-invisible {
position: absolute !important;
clip: rect(1px 1px 1px 1px); /* ie6, ie7 */
clip: rect(1px,1px,1px,1px);
}
.webuploader-pick {
position: relative;
display: inline-block;
cursor: pointer;
background: #00b7ee;
padding: 6px 15px;
color: #fff;
text-align: center;
border-radius: 3px;
overflow: hidden;
}
.webuploader-pick-hover {
background: #00a2d4;
}
.webuploader-pick-disable {
opacity: 0.6;
pointer-events:none;
}
.file-list{
width: 100%;
}
</style>
二、导出组件
var fileupload = require('./src/file_upload.vue');
module.exports = {
fileupload
}
三、demo 引用方式
<template>
<p>
<el-card class="box-card">
<fileupload ref="fileupload" :ext="ext" :countlimit="5" :tip="tip">aaa</fileupload>
</el-card>
</p>
</template>
<script>
import {fileupload} from '@/components/fileupload/index.js'
export default{
name: 'hello',
components: {fileupload},
data(){
return{
filelist: [],
ext: 'png,jpg,jpeg,mp3,mp4,pdf',
tip: '可上传png/jpg/jpeg/mp3/mp4/pdf,大小不超过200m'
}
},
created(){
},
methods: {
getfilelist: function(){
this.filelist = this.$refs.fileupload.getfilelist();
console.log(this.filelist);
}
}
}
</script>
四、运行效果图
相关推荐:
详解bootstrap fileinput文件上传组件的实例
fine uploader文件上传组件应用介绍_php教程
vue阿里云上传组件详解
以上就是webuploader文件上传组件的开发实例的详细内容。