当前位置:网站首页>基于WebUploader实现大文件分片上传
基于WebUploader实现大文件分片上传
2022-06-22 05:24:00 【Best_卡卡】
前言
前面叙述了如何利用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
- 封装上传组件upload.vue
封装好的组件upload.vue如下,接口可以根据具体的业务进行扩展。
<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
边栏推荐
- jedispool工具类
- Force buckle 33 [search rotation sort array]
- postmanUtils工具类,模拟postman的get,post请求
- 通达OA漏洞分析合集
- long start = currentTimeMillis();
- Topic selection system of college graduation design based on SSM
- 使用选择法对十个整数进行排序
- Which methods are not allowed to be overridden?
- Detailed explanation of OpenCV function usage 11~20, including code examples
- Hide symbol of dynamic library
猜你喜欢

使用keytool从.jks文件获取SSL certificate
![[cloud native] 2.2 kubeadm create cluster](/img/b2/a57b7e44f74357d5aedbb9ddcd95ff.png)
[cloud native] 2.2 kubeadm create cluster
Solve the shortage of developers. Maybe it can help you
![P1077 [noip2012 popularization group] flower display](/img/0d/f74a2036aa261ed327d9d74291aacc.png)
P1077 [noip2012 popularization group] flower display

Start with the strategy of small market value factor, and take you into quantitative investment (with the strategy of 77.83% annualized return)

C#中Cookie设置与读取

Accelerate the promotion of industrial Internet, and map out a new blueprint for development

使用选择法对十个整数进行排序

通达OA漏洞分析合集

What problems will be encountered during the implementation of MES management system
随机推荐
The benefits of implementing the standard of intellectual property in Miyun District, Beijing, with a subsidy of 50000-100000 yuan
DeformConv
通达OA漏洞分析合集
Storage mode and lifetime of C language variables
Small and medium-sized enterprises should pay attention to these points when signing ERP contracts
Traveler's budget (Los Angeles Valley)
JSON,字符串,map之间的互转
《MATLAB 神经网络43个案例分析》:第29章 极限学习机在回归拟合及分类问题中的应用研究——对比实验
P1160 queue arrangement
关于背包问题的总结
1108. Defanging an IP Address
Contents of 2022 tea master (intermediate) examination and tea master (intermediate) examination
Non recursive printing Fibonacci sequence
Sort ten integers using selection
Rambbmitmq Push Party
非递归打印斐波那契数列
冰河十年前的预测如今被阿里实现了,非常震撼
Kubernetes - bare metal cluster environment
使用keytool从.jks文件获取SSL certificate
YARN 的高可用设计有哪些?