赞
踩
前面叙述了如何利用vue-simple-uploader实现分片上传、断点续传和秒传;
本篇学习基于WebUploader实现这些功能
1.在项目中引入webuploader
注意事项
1、插件基于jquery,
2、不支持npm导入(通过 import './webuploader'; 的方式引入webuploader,会报''caller', 'callee', and 'arguments' properties may not be accessed on strict mode ...'的错,)
我们在项目index.html中进行静态引入资源
在 官网 上下载
Uploader.swf 和 webuploader.min.js,放到静态static文件下
注意事项
如遇到报错:Uncaught SyntaxError: Unexpected token ‘<‘,
是vue静态资源引入错误:https://blog.csdn.net/weixin_43909743/article/details/118804322
<template> <div class="upload"> </div> </template> <script> import { getToken } from "@/utils/auth"; // headers里面必须传递的token export default { name: 'vue-upload', props: { accept: { type: Object, default: null, }, // 上传地址 url: { type: String, default: '', }, // 上传最大数量 默认为100 fileNumLimit: { type: Number, default: 100, }, // 大小限制 默认2M fileSingleSizeLimit: { type: Number, default: 2048000, }, // 上传时传给后端的参数,一般为token,key等 formData: { type: Object, default: null }, // 生成formData中文件的key,下面只是个例子,具体哪种形式和后端商议 keyGenerator: { type: Function, default(file) { const currentTime = new Date().getTime(); const key = `${currentTime}.${file.name}`; return key; }, }, multiple: { type: Boolean, default: false, }, // 上传按钮ID uploadButton: { type: String, default: '', }, }, data() { return { uploader: null }; }, mounted() { this.initWebUpload(); }, methods: { initWebUpload() { this.uploader = WebUploader.create({ auto: true, // 选完文件后,是否自动上传 // swf: '/static/lib/webuploader/Uploader.swf', // swf文件路径 非必要 server: this.url, // 文件接收服务端 pick: { id: this.uploadButton, // 选择文件的按钮 multiple: this.multiple, // 是否多文件上传 默认false label: '', }, accept: this.getAccept(this.accept), // 允许选择文件格式。 threads: 3, fileNumLimit: this.fileNumLimit, // 限制上传个数 //fileSingleSizeLimit: this.fileSingleSizeLimit, // 限制单个上传图片的大小 formData: this.formData, // 上传所需参数 chunked: true, //分片上传 chunkSize: 2048000, //分片大小 duplicate: true, // 重复上传 headers: { Authorization: "Bearer " + getToken() }, }); // 当有文件被添加进队列的时候,添加到页面预览 this.uploader.on('fileQueued', (file) => { this.$emit('fileChange', file); }); this.uploader.on('uploadStart', (file) => { // 在这里可以准备好formData的数据 //this.uploader.options.formData.key = this.keyGenerator(file); }); // 文件上传过程中创建进度条实时显示。 this.uploader.on('uploadProgress', (file, percentage) => { this.$emit('progress', file, percentage); }); this.uploader.on('uploadSuccess', (file, response) => { this.$emit('success', file, response); }); this.uploader.on('uploadError', (file, reason) => { console.error(reason); this.$emit('uploadError', file, reason); }); this.uploader.on('error', (type) => { let errorMessage = ''; if (type === 'F_EXCEED_SIZE') { errorMessage = `文件大小不能超过${this.fileSingleSizeLimit / (1024 * 1000)}M`; } else if (type === 'Q_EXCEED_NUM_LIMIT') { errorMessage = '文件上传已达到最大上限数'; } else { errorMessage = `上传出错!请检查后重新上传!错误代码${type}`; } console.error(errorMessage); this.$emit('error', errorMessage); }); this.uploader.on('uploadComplete', (file, response) => { this.$emit('complete', file, response); }); }, upload(file) { this.uploader.upload(file); }, stop(file) { this.uploader.stop(file); }, // 取消并中断文件上传 cancelFile(file) { this.uploader.cancelFile(file); }, // 在队列中移除文件 removeFile(file, bool) { this.uploader.removeFile(file, bool); }, getAccept(accept) { switch (accept) { case 'text': return { title: 'Texts', exteensions: 'doc,docx,xls,xlsx,ppt,pptx,pdf,txt', mimeTypes: '.doc,docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt' }; break; case 'video': return { title: 'Videos', exteensions: 'mp4', mimeTypes: '.mp4' }; break; case 'image': return { title: 'Images', exteensions: 'gif,jpg,jpeg,bmp,png', mimeTypes: '.gif,.jpg,.jpeg,.bmp,.png' }; break; default: return accept } }, }, }; </script> <style lang="scss"> .webuploader-container { position: relative; } .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: 10px 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; } </style>
<el-form-item v-show="form.struct == 'single'&&form.courseType == 2" label="视频文件"> <div class="page"> <div id="filePicker">选择文件</div> <div class="file-panel"> <div class="file-list"> <ul class="file-item" :class="`file-${file.id}`" v-for="file in fileList1" v-show="!form.videoUrl"> <li class="file-type" :icon="fileCategory(file.ext)"></li> <li class="file-name">{{file.name}}</li> <li class="file-size">{{fileSize(file.size)}}</li> <li class="file-status">上传中...</li> <li class="progress"></li> <li @click="remove1(file)">关闭</li> </ul> <div class="no-file" v-if="!fileList1.length&&!form.videoUrl"><i class="iconfont icon-empty-file"></i> 暂无待上传文件</div> <div class="no-file" v-if="form.videoUrl"> <i class="iconfont icon-empty-file"></i> {{form.videoUrl}} <button @click="form.videoUrl=''">删除</button> </div> </div> </div> <vue-upload :url="url1" ref="uploader" uploadButton="#filePicker" @fileChange="fileChange" @progress="onProgress" @success="onSuccess" ></vue-upload> </div> </el-form-item>
data数据
fileList1: [],
url1:process.env.VUE_APP_BASE_API + "/file?type=1",
computed: {
uploader() {
return this.$refs.uploader;
}
},
methods:
fileChange(file) { if(this.fileList1.length){return this.$message.warning('一次只能上传一个文件')} if (!file.size) return; this.form.videoUrl='' this.fileList1.push(file); console.log(file); }, onProgress(file, percent) { $(`.file-${file.id} .progress`).css('width', percent * 99 + '%'); $(`.file-${file.id} .file-status`).html((percent * 99).toFixed(2) + '%'); }, onSuccess (file, response) { console.log('上传成功', response); this.fileList1=[] $(`.file-${file.id} .file-status`).html( '100%'); this.form.videoUrl = response.data.url }, resume(file) { this.uploader.upload(file); }, stop(file) { this.uploader.stop(file); }, remove1(file) { // 取消并中断文件上传 this.uploader.cancelFile(file); // 在队列中移除文件 this.uploader.removeFile(file, true); // 在ui上移除 let index = this.fileList1.findIndex(ele => ele.id === file.id); this.fileList1.splice(index, 1); }, fileSize(size) { return WebUploader.Base.formatSize(size); }, fileCategory(ext) { let type = ''; const typeMap = { image: ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp'], video: ['mp4', 'm3u8', 'rmvb', 'avi', 'swf', '3gp', 'mkv', 'flv'], text: ['doc', 'txt', 'docx', 'pages', 'epub', 'pdf', 'numbers', 'csv', 'xls', 'xlsx', 'keynote', 'ppt', 'pptx'] }; Object.keys(typeMap).forEach((_type) => { const extensions = typeMap[_type]; if (extensions.indexOf(ext) > -1) { type = _type } }); return type },
css
<style lang="scss"> $h-row: 50px; .file-panel { width: 100%; margin-top: 10px; box-shadow: 0 2px 12px 1px rgba(0, 0, 0, 0.1); > h2 { height: 40px; line-height: 40px; padding: 0 10px; border-radius: 4px 4px 0 0; border-bottom: 1px solid #ccc; background-color: #fff; } .file-list { position: relative; height: 100px; overflow-y: auto; background-color: rgb(250, 250, 250); } .file-item { position: relative; height: $h-row; line-height: $h-row; padding: 0 10px; border-bottom: 1px solid #ccc; background-color: #fff; z-index: 1; > li { display: inline-block; } } .file-type { width: 24px; height: 24px; vertical-align: -5px; } .file-name { width: 40%; margin-left: 10px; } .file-size { width: 20%; } .file-status { width: 20%; } .file-operate { width: 10%; > a { padding: 10px 5px; cursor: pointer; color: #666; &:hover { color: #ff4081; } } } .file-type[icon=text] { // background: url(../../assets/images/icon/text-icon.png); } .file-type[icon=video] { // background: url(../../assets/images/icon/video-icon.png); } .file-type[icon=image] { // background: url(../../assets/images/icon/image-icon.png); } .progress { position: absolute; top: 0; left: 0; height: $h-row - 1; width: 0; background-color: #E2EDFE; z-index: -1; } .no-file { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 16px; } } </style>
结果图
参考:
后端参考:https://glory.blog.csdn.net/article/details/114284285
参考链接:https://www.jb51.net/article/136113.htm
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。