在實際開發專案過程中有時候需要上傳比較大的檔案,然後呢,上傳的時候相對來說就會慢一些,so,後臺可能會要求前端進行檔案切片上傳,很簡單哈,就是把比如說1個G的檔案流切割成若干個小的檔案流,然後分別請求介面傳遞這個小的檔案流。
實現檔案切片匯入,首先我們使用 elementUI 也好,原生的 upload 標籤也好,獲取到檔案 file 檔案流,然後需要做的一件事情就是 知道這個檔案之前有沒有上傳過,我們需要向後臺提交一個這個檔案唯一的識別符號,然後讓後端告訴我們這個問題後臺有沒有,這時候,後端可能返回我們三種狀態:
檔案沒有,需要全部上傳。
這個檔案存在了,前端不需要再上傳。
這個檔案上傳了一部分,需要繼續把沒有上傳的部分上傳。
只有這三種狀態,實現這個步驟的一個重要引數就是這個檔案的唯一識別符號,這個識別符號,使用的就是這個檔案的 MD5 標識碼。所以我們首先需要獲取這個檔案的 MD5 唯一標識碼。【相關推薦:、】
我們知道檔案需要上傳或者是需要部分上傳的時候,我們就需要進行切片操作了。這個就很簡單了,比如檔案的二進位制位元組流一共1個G,然後一般是 5M 切一片,所以說如果是1個G 的檔案需要切 205 片,當然最後一片不一定是 5M,然後我們走檔案分片上傳的介面,發起檔案分片匯入的請求。
首先明確一點,就是我們把這 205 個分片資料流提交完,後臺是需要合併的,就是把我們分片提交的在這 205 個檔案流合成一個大的檔案儲存起來,這樣,後臺合併完的檔案就是我們最終要提交匯入的檔案,既然後端需要合併,我們又是一片一片上傳的,總得讓後端知道每一片是這個檔案的哪一部分吧?所以說我們提交分片請求的時候一般需要傳遞這幾個引數:
這樣後端就知道怎麼去合併最後的檔案了。當然了具體的欄位需要後端去定義,然後我們按照這個思路去相應的對接就可以了。
OK,等我們 205 個分片資料全部提交完成,需要再走一個介面,就是通知後端,好了,我前端分片都傳完了,你可以合併檔案了。
然後後端合併完成,檔案匯入成功!
很多人說哈,MD5 不是加密嘛,其實這個想法在這裡不是很對哈,MD5 是加密不了檔案的,只會生成一個唯一的編碼,這麼說呢,哎喲,就當是加密吧,但是別妄想提交一個 MD5 編碼就當把加密的檔案提交給後端了哈,首先這個就是一個字串,不是加密的檔案,第二,這個玩意並不能解密。我們這裡只是給檔案生成一個唯一識別符號,讓後端判斷伺服器之前有沒有存在過這個檔案,如果唯一標識有的話,就說明之前上傳過,直接用之前的就可以了,就不用再次上傳了,畢竟如果檔案修改了,這個 MD5 標識碼是會變的。
怎麼獲取檔案的 MD5 編碼很簡單哈,在vue裡面需要使用一個庫 。
一句命令安裝
npm install --save spark-md5
登入後複製
然後我們可以寫一個方法來封裝一下。
建立一個 fileMd5Sum.js 檔案:
import SparkMD5 from 'spark-md5'
export default {
// md5值計算
fileMd5Sum(file) {
return new Promise(resolve => {
let fileReader = new FileReader()
let Spark = new SparkMD5.ArrayBuffer()
fileReader.readAsArrayBuffer(file)
fileReader.onload = function (e) {
Spark.append(e.target.result)
let md5 = Spark.end()
resolve(md5)
}
});
}
}
登入後複製
然後在需要使用的時候就可以使用了,當然這裡返回的是一個 Promise,直接 .then
就可以獲取了。
或者是使用 async、 await
。
let md5Str = await this.fileMd5Sum.fileMd5Sum(file.raw)
登入後複製
獲取了檔案MD5標識碼,後臺說需要提交,我們就需要把檔案切片,從頭提交或者是提交部分操作了,如果不需要的話直接走合併介面就可以了,走合併介面其實是告訴後臺合併,我們要做的就是把其他除了檔案相關的其他引數傳遞給後臺罷了。
檔案切片就是類似於字串擷取,這裡是擷取位元組。獲取需要的引數我們自己些就可以了。假設我們使用 elementUI 檔案上傳元件獲取到了檔案 file
。
let fileName = file.name // 獲取檔名
登入後複製
let chunkSize = 5 * 1024 * 1024 // 一般是 5M,具體多少看後端想要多少
登入後複製
let chunkList = [] // 建立一個陣列用來儲存每一片檔案流資料
if (file.size < chunkSize) { // 如果檔案大小小於5M就只有一片,不用切都
chunkList.push(file.raw.slice(0)) // 檔案流從第一個位元組直接擷取到最後就可以了
} else { // 如果檔案大小大於5M 就需要切片了
var start = 0, end = 0 // 建立兩個變數 開始位置 結束位置
while (true) { // 迴圈
end += chunkSize // 結束為止 = 結束位置 + 每片大小
let blob = file.raw.slice(start, end) // 檔案流從開始位置擷取到結束位置
start += chunkSize // 擷取完,開始位置後移
if (!blob.size) { // 如果擷取不到了就退出
break;
}
chunkList.push(blob) // 把擷取的每一片資料儲存到陣列
}
}
登入後複製
我們上一步已經獲取到每片檔案流的陣列了,所以說呢,直接獲取就可以了。
let chunks = chunkList.length
登入後複製
我們是按照 5 M 切割的,所以說每片大小應該是 5 * 1024 * 1024
但是呢,不對,因為最後一片不一定就是正好的 5 M,所以說我們可直接 .size
獲取一下大小。比如:
chunkList[0].size // 獲取第1片大小
登入後複製
引數都找齊了,然後就走切片提交介面開始提交資料就可以了。
當我們把分片資料全部提交成功,後臺返回說切片檔案儲存成功之後,我們就可以走最後一個介面,提交就可以了。
好了,就這樣!完成!!!
(學習視訊分享:、)
以上就是淺析vue怎麼實現檔案切片上傳的詳細內容,更多請關注TW511.COM其它相關文章!