vue大文件分片上傳之simple-uploader.js的使用
關(guān)于大文件上傳
關(guān)于單個文件上傳:其實就是前端中的文件
通過http
傳到后端
,后端再寫入服務(wù)器
的過程
那單個大文件分片
上傳:其實就是前端把大文件分成了好幾塊
,后端再多次寫入服務(wù)器的過程
關(guān)于秒傳與斷點續(xù)傳
秒傳:其實就是服務(wù)器中存在這個文件了
,再次傳的時候就不重新上傳
了,前端直接顯示上傳成功
斷點續(xù)傳:其實就是文件傳了一部分
,剩下的還沒傳。這個時候根據(jù)上傳的偏移量offset
,把剩下的上傳
到服務(wù)器
前提知識
1. 前端使用spark-md5.js對文件進(jìn)行加密
import SparkMD5 from 'spark-md5' const spark = new SparkMD5.ArrayBuffer() //獲取文件二進(jìn)制數(shù)據(jù) var fileReader = new FileReader() fileReader.readAsArrayBuffer(file) //file就是獲取到的文件 //異步執(zhí)行函數(shù),fileReader.readAsArrayBuffer的回調(diào)函數(shù) fileReader.onload = function (e) { spark.append(e.target.result) const md5 = spark.end() console.log(md5) //打印結(jié)果這個文件會有一串唯一編碼類似下面 //4b4a94c7ff8953d7103515e91d432b0a }
2. simple-uploader.js的使用
// options常見配置 options: { // 上傳地址,若測試和真正上傳接口不是同個路徑,可以用函數(shù)模式。 // 如果是同一個路徑,一個get請求,一個post請求 target: "/fileStorage/upload", // 是否開啟服務(wù)器分片校驗。默認(rèn)為 true testChunks: true, // 真正上傳的時候使用的 HTTP 方法,默認(rèn) POST uploadMethod: "post", // 分片大小 chunkSize: CHUNK_SIZE, // 并發(fā)上傳數(shù),默認(rèn)為 3 simultaneousUploads: 3, /** * 檢測校驗是md5加密以后的事情,整個上傳過程,只會執(zhí)行一次。 * 執(zhí)行一次以后,看是上傳完成,還是需要繼續(xù)上傳 * * 發(fā)起測試校驗以后,所有分片都會進(jìn)入這個回調(diào) * * 判斷分片是否上傳,秒傳和斷點續(xù)傳基于此方法 * 如果后端返回的是true,代表秒傳 * 如果后端返回[1,2,3,4,5,6,7,8,9]等(分片信息),代表可以繼續(xù)上傳 * * * 我個人理解的停止上傳與繼續(xù)上傳就是斷點上傳 * * * 我個人理解這個方法是這樣的:分塊以后知道有幾塊了,再跟數(shù)據(jù)庫做比對,知道是上傳完成了,還是需要繼續(xù)上傳 * api接口只走一次檢驗方法,那如果是上傳完成了直接ok,如果是需要繼續(xù)上傳,那就接著上傳,組件再暴露出pause和resume方法,用于停止和繼續(xù)上傳。(api得到數(shù)據(jù)庫數(shù)據(jù)以后,每塊走這個方法,進(jìn)行對比。) */ checkChunkUploadedByResponse: (chunk, message) => { console.log("message,第一次test以后,返回來的數(shù)據(jù)", chunk.offset) // message是后臺返回 let messageObj = JSON.parse(message); let dataObj = messageObj.data; if (dataObj.uploaded !== null) { return dataObj.uploaded; } // 判斷文件或分片是否已上傳,已上傳返回 true // 這里的 uploadedChunks 是后臺返回 return (dataObj.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0; }, parseTimeRemaining: function (timeRemaining, parsedTimeRemaining) { //格式化時間 return parsedTimeRemaining .replace(/\syears?/, "年") .replace(/\days?/, "天") .replace(/\shours?/, "小時") .replace(/\sminutes?/, "分鐘") .replace(/\sseconds?/, "秒"); }, // 處理所有請求的參數(shù) // processParams:(params,file,chunk) => { // // 這里需要根據(jù)后端的要求,處理一些請求參數(shù) // // params.xxx = chunk.xxx // 比如一些需要在上傳時,帶上測試校驗返回的一些信息字段 // // return params; // } },
// 常用的回調(diào)函數(shù) <uploader ref="uploader" :options="options" :autoStart="false" :file-status-text="fileStatusText" @file-added="onFileAdded" @file-success="onFileSuccess" @file-error="onFileError" @file-progress="onFileProgress" class="uploader-example" >
分片上傳的思路
- 先對文件進(jìn)行md5加密。使用md5加密的優(yōu)點是:可以對文件進(jìn)行唯一標(biāo)識。在后端根據(jù)md5判斷文件是否存在。
- 向后臺發(fā)送第一次請求接口,且只發(fā)送一次,用于檢測,接口里的數(shù)據(jù)就是我們已經(jīng)上傳過的文件塊。用于檢測是否需要秒傳或者繼續(xù)上傳
- 當(dāng)文件存在的話,就不用重新再上傳。(秒傳)
- 當(dāng)文件不存在的話,且對大文件進(jìn)行分片。比如一個100M的文件,我們一個分片是5M的話,那么這個文件可以分20次上傳。(checkChunkUploadedByResponse方法里面判斷)
- 當(dāng)文件不存在的話,且已經(jīng)上傳了一部分的。接著上傳(checkChunkUploadedByResponse方法里面判斷)
- 向后臺發(fā)送第二次請求接口,這時的請求才是正兒八經(jīng)的上傳請求。此時,請求可以停止和繼續(xù)發(fā)。
前端文件切片常見的寫法
// 文件切片需要是的參數(shù): 1. var fileSize = file.size; // 文件大小 2. var CHUNK_SIZE = 2 * 1024 * 1024; // 切片的大小 3. var chunks = Math.ceil(fileSize / chunkSize); // 獲取切片的個數(shù) 4. var currentChunk = 0; // 當(dāng)前分片下標(biāo) // 加載下一個分片的start與end const start = currentChunk * CHUNK_SIZE; const end = start + CHUNK_SIZE >= file.size ? file.size : start + CHUNK_SIZE;
// md5 加密 getFileMD5(file, callback) { // 使用SparkMD5,對文件進(jìn)行加密 let spark = new SparkMD5.ArrayBuffer(); let fileReader = new FileReader(); //獲取文件分片對象(注意它的兼容性,在不同瀏覽器的寫法不同) let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; // 當(dāng)前分片下標(biāo) let currentChunk = 0; // 分片總數(shù)(向下取整) let chunks = Math.ceil(file.size / CHUNK_SIZE); // 暫停上傳 file.pause(); // 第一次加載分片的方法 loadNext(); // fileReader.readAsArrayBuffer,讀完后的回調(diào)函數(shù) fileReader.onload = function (e) { // console.log("currentChunk :>> ", currentChunk); spark.append(e.target.result); if (currentChunk < chunks) { currentChunk++; loadNext(); } else { // 該文件的md5值 let md5 = spark.end(); // 回調(diào)傳值md5 callback(md5); } }; fileReader.onerror = function () { this.$message.error("文件讀取錯誤"); file.cancel(); }; // 加載下一個分片 function loadNext() { const start = currentChunk * CHUNK_SIZE; const end = start + CHUNK_SIZE >= file.size ? file.size : start + CHUNK_SIZE; // 文件分片操作,讀取下一分片(fileReader.readAsArrayBuffer操作會觸發(fā)onload事件) fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end)); } },
// @file-added="onFileAdded" 回調(diào)函數(shù) onFileAdded(file, event) { console.log("onFileAdded方法執(zhí)行了__flx",event) /* * 第一步,判斷文件類型是否允許上傳 * */ // todo 判斷文件類型是否允許上傳 /* * 第二步:計算文件 MD5,并恢復(fù)上傳 * */ this.getFileMD5(file, (md5) => { console.log('MD5回調(diào)函數(shù)') if (md5 !== "") { // 修改文件唯一標(biāo)識 file.uniqueIdentifier = md5; // 請求后臺判斷是否上傳 // 恢復(fù)上傳 file.resume(); } }); },
后端常見的寫法
// 校驗接口的業(yè)務(wù)邏輯 // 一共兩張表,一張是每塊的記錄表(chunck),一張是上傳完成的記錄表(file) // chunck表中的操作 // 1. 根據(jù) identifier 查找數(shù)據(jù)是否存在 // 2. 如果查詢的List的length是 0 說明文件不存在,則直接返回沒有上傳 // 3. 如果不是0,則拿到第一個數(shù)據(jù),查看文件是否分片 // 4. 如果沒有分片,那么直接返回已經(jīng)上傳成功,否則返回分片數(shù)據(jù)。
// 分片上傳的邏輯 // 1. 每次上傳完成以后,都把數(shù)據(jù)存到chunck表中 // 2. 當(dāng)所有都上傳完以后,存到文件表file中
到此這篇關(guān)于vue大文件分片上傳之simple-uploader.js的使用的文章就介紹到這了,更多相關(guān)vue大文件分片上傳內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用eventBus遇到數(shù)據(jù)不更新的問題及解決
這篇文章主要介紹了vue使用eventBus遇到數(shù)據(jù)不更新的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Vue-router 類似Vuex實現(xiàn)組件化開發(fā)的示例
本篇文章主要介紹了Vue-router 類似Vuex實現(xiàn)組件化開發(fā)的示例,具有一定的參考價值,有興趣的可以了解一下2017-09-09