集团网站建设工作方案,大型网站注意哪些,网站结构是什么,平台投诉怎么投诉Vue项目中遇到了大文件分片上传的问题#xff0c;之前用过webuploader#xff0c;索性就把Vue2.0与webuploader结合起来使用#xff0c;封装了一个vue的上传组件#xff0c;使用起来也比较舒爽。
上传就上传吧#xff0c;为什么搞得那么麻烦#xff0c;用分片上传#x…Vue项目中遇到了大文件分片上传的问题之前用过webuploader索性就把Vue2.0与webuploader结合起来使用封装了一个vue的上传组件使用起来也比较舒爽。
上传就上传吧为什么搞得那么麻烦用分片上传
分片与并发结合将一个大文件分割成多块并发上传极大地提高大文件的上传速度。当网络问题导致传输错误时只需要重传出错分片而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。实现后的界面主要是两个文件封装的上传组件和具体的ui页面上传组件代码下面有列出来。这两个页面的代码放到github上了https://github.com/shady-xia/Blog/tree/master/vue-webuploader。
在项目中引入webuploader
先在系统中引入jquery插件基于jq坑爹啊如果你不知道放哪那就放到index.html中。在官网上下载Uploader.swf和webuploader.min.js可以放到项目静态目录static下面在index.html中引入webuploader.min.js。无需单独再引入webuploader.css因为没有几行css我们可以复制到vue组件中。
script src/static/lib/jquery-2.2.3.min.js/script
script src/static/lib/webuploader/webuploader.min.js/script需要注意的点
在vue组件中通过import ./webuploader;的方式引入webuploader会报caller, callee, and arguments properties may not be accessed on strict mode ...的错 这是因为你的babel使用了严格模式而caller这些在严格模式下禁止使用。所以可以直接在index.html中引入webuploader.js或者手动去解决babel中use strict的问题。基于webuploader封装Vue组件
封装好的组件upload.vue如下接口可以根据具体的业务进行扩展。
注意功能和ui分离此组建封装好了基本的功能没有提供uiui在具体的页面上去实现。
templatediv classupload/div
/template
scriptexport default {name: vue-upload,props: {accept: {type: Object,default: null,},// 上传地址url: {type: String,default: ,},// 上传最大数量 默认为100fileNumLimit: {type: Number,default: 100,},// 大小限制 默认2MfileSingleSizeLimit: {type: Number,default: 2048000,},// 上传时传给后端的参数一般为tokenkey等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,},// 上传按钮IDuploadButton: {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, // 是否多文件上传 默认falselabel: ,},accept: this.getAccept(this.accept), // 允许选择文件格式。threads: 3,fileNumLimit: this.fileNumLimit, // 限制上传个数//fileSingleSizeLimit: this.fileSingleSizeLimit, // 限制单个上传图片的大小formData: this.formData, // 上传所需参数chunked: true, //分片上传chunkSize: 2048000, //分片大小duplicate: true, // 重复上传});// 当有文件被添加进队列的时候添加到页面预览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 langscss
// 直接把官方的css粘过来就行了
/style使用封装好的上传组件
新建页面使用例子如下
ui需要自己去实现。大概的代码可以点这里。
vue-uploadrefuploaderurlxxxxxxuploadButton#filePickermultiplefileChangefileChangeprogressonProgresssuccessonSuccess
/vue-upload
分片的原理及流程
当我们上传一个大文件时会被插件分片ajax请求如下多个upload请求均为分片的请求把大文件分成多个小份一次一次向服务器传递分片完成后即upload完成后需要向服务器传递一个merge请求让服务器将多个分片文件合成一个文件
分片
可以看到发起了多次upload的请求我们来看看upload发送的具体参数第一个配置(content-disposition)中的guid和第二个配置中的access_token是我们通过webuploader配置里的formData即传递给服务器的参数后面几个配置是文件内容id、name、type、size等其中chunks为总分片数chunk为当前第几个分片。图片中分别为12和9。当你看到chunk是11的upload请求时代表这是最后一个upload请求了。合并
分片后文件还未整合数据大概是下面这个样子做完了分片后其实工作还没完我们还要再发送个ajax请求给服务器告诉他把我们上传的几个分片合并成一个完整的文件。
我怎么知道分片上传完了我在何时做合并webuploader插件有一个事件是uploadSuccess包含两个参数file和后台返回的response当所有分片上传完毕该事件会被触发我们可以通过服务器返回的字段来判断是否要做合并了。比如后台返回了needMerge我们看到它是true的时候就可以发送合并的请求了。存在的已知问题
在做单文件暂停与继续上传时发现了这个插件的bug
1、当设置的threads1使用单文件上传功能即stop方法传入file时会报错Uncaught TypeError: Cannot read property file of undefined
出错的源码如下这是因为暂停时为了让下一个文件继续传输会将当前的pool池中pop掉暂停的文件流。这里做了循环最后一次循环的时候v是undefined的。2、设置的threads为1能正常暂停但是暂停后再继续上传是失败的。
原理和上一个一样暂停时把当前文件流在pool中全部pop了当文件开始upload的时候会检查当期pool而此时已经没有之前暂停的文件流了。
如果是针对所有文件整体的暂停和继续功能是正常的。如果想实现单文件的暂停和继续功能需要修改源码我改了下源码发现耦合度较高工程量比想象的大遂放弃