利用 html5 的新特性分割文件,爲達到斷點續傳功能
用 spark.js 獲取文件md5以確保文件的惟一性
流程概述:
(此功能前端共需調用3個接口,分別爲簡稱做 A / B / C)
1,獲取文件信息:使用HTML5的原生上傳input,選擇文件後,獲取文件的全部信息(文件名、文件總字節數等)
2,計算總切片:跟後臺約定好單個切片大小,好比1M/片,計算文件總大小/單個切片大小=總切片數
3,計算文件MD5和每一個切片的MD5:引用spark-md5.min.js來生成MD5,此js的調用能夠獲取文件MD五、切片的MD5和切片的數據
4,調用A接口查詢從第幾個切片開始上傳:須要向後臺傳入的關鍵參數是文件名、文件總大小、文件的MD5
5,獲取到初始上傳切片位置,正式開始分片上傳到服務器:從A接口獲取到切片位置後,調用接口B,將切片的MD5和切片數據傳給後臺,此後循環調用接口B,直到最後一切片上傳結束
6,全部切片上傳結束後,調用接口C將文件存庫
複製代碼
詳細代碼展現:
HTML:
<input type='file' title="" accept=".mp4"
name='myfiles' id="mediaFile" class ="" onchange="handleFile()" />
複製代碼
獲取文件信息:
function handleFile ( ) {
var fileInputs = $("input[name='myfiles']" )[0 ];
var name = fileInputs.files[0 ].name,
size = fileInputs.files[0 ].size,
type = fileInputs.files[0 ].type,
shardSize = 1024 * 1024 ,
shardCount = Math .ceil(size / shardSize);
}
複製代碼
計算整個文件的MD5:(前提是引入了spark.js,下載地址: js-spark-md5 )
var singleFileData = new Array ();
var fileReader = new FileReader(),
blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice,
chunkSize = shardSize ,
chunks = shardCount,
currentChunk = 0 ;
var spark = new SparkMD5.ArrayBuffer();
fileReader.onload = function (e ) {
for (var i = 0 ; i < chunks; i++) {
var start = i * chunkSize,
end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
var sliceFile = blobSlice.call(file, start, end);
getChunkMd5(sliceFile, i);
}
spark.append(e.target.result);
if (currentChunk < chunks) {
currentChunk++;
loadNext();
} else {
var allFileEnd = spark.end()
console .log("此值爲整個切片的MD5" , allFileEnd)
}
};
function loadNext ( ) {
var start = currentChunk * chunkSize,
end = start + chunkSize >= file.size ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
if (singleFileData.length != chunks) {
singleFileData.push(blobSlice.call(file, start, end))
}
};
loadNext()
複製代碼
計算切片的MD5:
(此步驟其實能夠省略,但爲了嚴謹後端須要根據前端傳入的切片數據計算出MD5,跟前端傳入的MD5對比)
var mySingleFileMd5 = []; //用於儲存全部切片的MD5
function getChunkMd5(file, i) {
var spark = new SparkMD5.ArrayBuffer();
var fileReader = new FileReader();
fileReader.onload = function (e) {
spark.append(e.target.result);
mySingleFileMd5[i] = spark.end();// 將每一個切片的MD5存起來
console.log("全部切片的MD5數組=", mySingleFileMd5);
}
fileReader.onerror = function () {
console.warn('oops, something went wrong');
}
function loadNext() {
fileReader.readAsArrayBuffer(blobSlice.call(file, 0, file.size));
}
loadNext();
}
複製代碼
調用接口A後獲取到 PARTINDEX(從第幾個切片開始上傳),接着調用接口B進行上傳,上傳後手動計算進度。
A接口傳參、取參以下:
var params = {
serviceid : 'wcm61_bigfile' ,
methodname : 'startUpload' ,
fileName : 手機QQ視頻_20181212094958.mp4,
fileDigest : 65309 fc9684b4eb2f3d281da5ad17b6e,
fileSize : 100904886 ,
};
{
"MSG" :"操做成功" ,
"DATA" :{
"TOTALPARTCOUNT" :"49" ,
"PARTINDEX" :"1" ,
"PARTSIZE" :"2097152" ,
"FLAG" :"1" ,
"FILENAME" :"手機QQ視頻_20181212094958.mp4"
},
"ISSUCCESS" :"true"
}
複製代碼
B接口傳參、取參以下:
var data = singleFileData[partIndex - 1 ]
var fileName =手機QQ視頻_20181212094958.mp4;
var fileDigest = 65309 fc9684b4eb2f3d281da5ad17b6e;
var partIndex = 1 ;
var partDigest = ea58e21870ad4c22f2c75645564654b2;
{
"filename" :"手機QQ視頻_20181212094958.mp4" ,
"PARTINDEX" :"2" ,
"PARTSIZE" :"2097152" ,
"totalPartCount" :"49"
"ISSUCCESS" :"1"
}
複製代碼
經過B接口,不斷將切片上傳到服務器,而且實時計算上傳進度
var processNum =
parseInt ((PARTINDEX - 1 ) / totalPartCount * 100 )
複製代碼
最終實現靜態效果和接口以下: