使用插件 vue-simple-uploader
npm install vue-simple-uploader --save
npm install spark-md5 --save
main.js 中添加
import uploader from 'vue-simple-uploader'; Vue.use(uploader); 在应用页面中引入并使用 <uploader ref="uploader" :options="options" :autoStart='false' :multipl="false" :limit="1" :file-status-text="fileStatusText" @file-added="onFileAdded" @file-success="onFileSuccess" @file-progress="onFileProgress" @file-error="onFileError" class="uploader-ui"> <uploader-unsupport></uploader-unsupport> <uploader-drop> <div> <uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn">选择文件<i class="el-icon-upload el-icon--right"></i></uploader-btn> </div> </uploader-drop> <uploader-list></uploader-list> </uploader> import {ACCEPT_CONFIG} from './config'; import SparkMD5 from 'spark-md5'; ( 备注:'./config.js'是一个js文件存放上传文件类型: export const ACCEPT_CONFIG = { image: ['.png', '.jpg', '.jpeg', '.gif', '.bmp'], video: ['.mp4', '.rmvb', '.mkv', '.wmv', '.flv'], document: ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf', '.txt', '.tif', '.tiff','.rar','.zip'], getAll(){ return [...this.image, ...this.video, ...this.document] }, }; ) data(){ return { options: { //目标上传 URL,默认POST target: process.env.VUE_APP_BASE_API+"/api/questionBank/uploadFile", //分块大小(单位:字节) chunkSize: '2048000', //上传文件时文件内容的参数名,对应chunk里的Multipart对象名,默认对象名为file fileParameterName: 'upfile', //失败后最多自动重试上传次数 maxChunkRetries: 3, //是否开启服务器分片校验,对应GET类型同名的target URL testChunks: true, /* 服务器分片校验函数,判断秒传及断点续传,传入的参数是Uploader.Chunk实例以及请求响应信息 reponse码是successStatuses码时,才会进入该方法 reponse码如果返回的是permanentErrors 中的状态码,不会进入该方法,直接进入onFileError函数 ,并显示上传失败 reponse码是其他状态码,不会进入该方法,正常走标准上传 checkChunkUploadedByResponse函数直接return true的话,不再调用上传接口 */ checkChunkUploadedByResponse: function (chunk, response_msg) { let objMessage = JSON.parse(response_msg); if (objMessage.skipUpload) { return true; } return (objMessage.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0; } }, attrs: { accept: ACCEPT_CONFIG.getAll() }, fileStatusText: { success: '上传成功', error: '上传失败', uploading: '上传中', paused: '暂停', waiting: '等待上传' }, } } methods: { onFileProgress(rootFile, file, chunk) { console.log(`上传中 ${file.name},chunk:${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`) }, onFileAdded(file) { this.computeMD5(file); }, /* 第一个参数 rootFile 就是成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件; 第二个参数 file 就是当前成功的 Uploader.File 对象本身; 第三个参数就是 message 就是服务端响应内容,永远都是字符串; 第四个参数 chunk 就是 Uploader.Chunk 实例,它就是该文件的最后一个块实例,如果你想得到请求响应码的话,chunk.xhr.status就是 */ onFileSuccess(rootFile, file, response, chunk) { //refProjectId为预留字段,可关联附件所属目标,例如所属档案,所属工程等 file.refProjectId = "123456789"; // mergeFile(file).then( responseData=> { // if(responseData.data.code === 415){ // console.log("合并操作未成功,结果码:"+responseData.data.code); // } // }).catch(function (error){ // console.log("合并后捕获的未知异常:"+error); // }); }, onFileError(rootFile, file, response, chunk) { console.log('上传完成后异常信息:'+response); }, /** * 计算md5,实现断点续传及秒传 * @param file */ computeMD5(file) { file.pause(); console.log(process.env.VUE_APP_BASE_API) //单个文件的大小限制2G let fileSizeLimit = 2 * 1024 * 1024 * 1024; console.log("文件大小:"+file.size); console.log("限制大小:"+fileSizeLimit); if(file.size > fileSizeLimit){ this.$message({ showClose: true, message: '文件大小不能超过2G' }); file.cancel(); } let fileReader = new FileReader(); let time = new Date().getTime(); let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; let currentChunk = 0; const chunkSize = 10 * 1024 * 1000; let chunks = Math.ceil(file.size / chunkSize); let spark = new SparkMD5.ArrayBuffer(); //由于计算整个文件的Md5太慢,因此采用只计算第1块文件的md5的方式 let chunkNumberMD5 = 1; loadNext(); fileReader.onload = (e => { spark.append(e.target.result); if (currentChunk < chunkNumberMD5) { loadNext(); } else { let md5 = spark.end(); file.uniqueIdentifier = md5; file.resume(); console.log(`MD5计算完毕:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${file.size} 用时:${new Date().getTime() - time} ms`); } }); fileReader.onerror = function () { this.error(`文件${file.name}读取出错,请检查该文件`) file.cancel(); }; function loadNext() { let start = currentChunk * chunkSize; let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end)); currentChunk++; console.log("计算第"+currentChunk+"块"); } }, close() { this.uploader.cancel(); }, error(msg) { this.$notify({ title: '错误', message: msg, type: 'error', duration: 2000 }) }, }
参考地址:https://www.cnblogs.com/xiahj/p/vue-simple-uploader.html