Vue.js实现大文件分片md5断点续传
2019-08-14 10:00:29来源:博客园 阅读 ()
背景
根据部门的业务需求,需要在网络状态不良的情况下上传很大的文件(1G+)。
其中会遇到的问题:
1,文件过大,超出服务端的请求大小限制;
2,请求时间过长,请求超时;
3,传输中断,必须重新上传导致前功尽弃。
解决方案实现思路,拿到文件,保存文件唯一性标识,切割文件、分片上传、文件MD5验证、断点续传、手动重试上传。
前言
鉴于过往有使用过webupload文件上传组件的经验,于是此次采用的是Plupload作为替换。Plupload是一款由著名的web编辑器TinyMCE团队开发的上传组件,简单易用且功能强大。
Plupload有以下功能和特点
- 拥有多种上传方式:HTML5、flash、silverlight以及传统的
<input type=”file” />
。Plupload会自动侦测当前的环境,选择最合适的上传方式,并且会优先使用HTML5的方式。所以你完全不用去操心当前的浏览器支持哪些上传方式,Plupload会自动为你选择最合适的方式。 - 支持以拖拽的方式来选取要上传的文件
- 支持在前端压缩图片,即在图片文件还未上传之前就对它进行压缩
- 可以直接读取原生的文件数据,这样的好处就是例如可以在图片文件还未上传之前就能把它显示在页面上预览
- 支持把大文件切割成小片进行上传,因为有些浏览器对很大的文件比如几G的一些文件无法上传。
环境
- vue2.x
- webpack3.x
- axios
代码
npm安装plupload,文件引入组件,
<uploader browse_button="upload_area" :max_retries="3" :url="action" :headers="headers" chunk_size="10MB" drop_element="upload_area" @disableBrowse="!loading" :BeforeUpload="beforeUpload" :ChunkUploaded="chunkUploaded" :FilesAdded="filesAdded" :StateChanged="stateChanged" @inputUploader="inputUploader" />
初始化方法filesAdded(),每次上传前清空队列的其他文件,保证上传的一致性。其次对文件类型进行判断过滤fileType(),文件进入时进行总md5一次fileMd5(),然后进入文件分片chunkCheckStatus(),每个分片都要进行md5并与后台进行校验fileMd5(),确保文件在中断后继续上传的准确性。
filesAdded (up, files) { // 删除上传队列中其他文件,只保留最近上传的文件 let fileLen = files.length, that = this if (fileLen > 1) { files = files.splice(0, fileLen - 1)// 清空上传队列 } files.forEach((f) => { f.status = -1 that.dataForm.file = f that.fileType(f.getNative()) if (that.loading) { that.computeStatus = true that.progress = 0 // 文件分片 let chunkSize = 2097152, // Read in chunks of 2MB chunks = Math.ceil(f.size / chunkSize) that.fileMd5(f.getNative(), (e, md5) => { that.dataForm.md5 = md5 if (that.loading == true) { that.count = 0 that.chunkCheckStatus(md5, that.dataForm.fileName, (uploader, dataList) => { that.uploading = uploader if (that.uploading == true) { for (let chunk = 1; chunk <= chunks; chunk++) { that.fileChunkFile(f.getNative(), chunk, (e, chunkFile) => { that.fileMd5(chunkFile, (e, blockMd5) => { that.PostFile(up, chunkFile, chunk, chunks, md5, blockMd5) }) }) } } else { // 去重 that.progress = 0 for (let chunk = 1; chunk <= chunks; chunk++) { let status = 0 dataList.some((item) => { if (item.chunk == chunk) { status = 1 return false } }) if (status == 0) { that.fileChunkFile(f.getNative(), chunk, (e, chunkFile) => { that.fileMd5(chunkFile, (e, blockMd5) => { that.PostFile(up, chunkFile, chunk, chunks, md5, blockMd5) }) }) } } } }) } }) } }) }
文件md5方法,这里使用了SparkMD5,import SparkMD5 from 'spark-md5'
fileMd5 (file, callback) { let that = this var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, file = file, chunkSize = 2097152, // Read in chunks of 2MB chunks = Math.ceil(file.size / chunkSize), currentChunk = 0, spark = new SparkMD5.ArrayBuffer(), fileReader = new FileReader() fileReader.onload = function (e) { console.log('read chunk nr', currentChunk + 1, 'of', chunks) spark.append(e.target.result) // Append array buffer currentChunk++ if (currentChunk < chunks) { loadNext() } else { let blockMd5 = '' blockMd5 = spark.end() callback(null, blockMd5) } } fileReader.onerror = function () { callback('oops, something went wrong.') } function loadNext () { var start = currentChunk * chunkSize, end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)) } loadNext() }
文件分片上传方法,验证总分片信息后,把每个分片进行md5加密并上传校验,这里有写进度条相关的控制,不一一展示
chunkCheckStatus (md5, fileName, callback) { this.$http({ url: this.$http.adornUrl('/biz/upload/getFileBlockStatus'), method: 'get', params: this.$http.adornParams({ md5: md5, fileName: fileName }) }).then(({ data }) => { if (data && data.code === 0) { if (data.list != null) { this.uploading = false this.chunkCheckData = [] data.list.map((item, index) => { if (item.isUpload == true) { this.count++ this.chunkCheckData.push(item) } }) callback(this.uploading, this.chunkCheckData) return } this.uploading = true callback(this.uploading) } else { this.$message.error(data.msg) this.loading = false this.computeStatus = false return false } }) }
总结
上图可以清晰的说明文件加密上传的传输流程,在文件上传加密及Content-Type格式需要与后台协商一致,通常有base64、multipart/form-data两种类型,要清晰了解分片算法及md5,自定义上传文件异步代码,除此之外,可拖拽上传文件、进度条控制等可更好的丰富文件上传体验。
注意
功能在某些旧版浏览器中不起作用。
参考
https://www.plupload.com/
原文链接:https://www.cnblogs.com/wpshan/p/11119627.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- js防止表单重复提交实现代码 2020-03-29
- 基于JQuery的多标签实现代码 2020-03-29
- js实现翻页后保持checkbox选中状态的实现方法 2020-03-25
- NiftyCube实现圆角边框的方法 2020-03-20
- 根据分辨率调用css文件的方法 2020-03-19
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash