<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input type="file" id="file" onchange="fileChange(this)" />
<button onclick="download()">download</button>
<script type="text/javascript">
let fileData = [];
let file
async function fileChange (e) {
if (e.files.length > 0 && (await valid(e.files[0], "jpg,png,gif"))) {
file = e.files[0]
let blobArray = sliceUp(e.files[0], 10 * 1024);
sendblob(blobArray, 5, e.files[0].size);
}
}
function sliceUp (blob, bytesPerPiece = 5 * 1024 * 1024) {
let start = 0,
end = 0,
index = 0,
filesize = blob.size,
blobArray = [];
//計算文件切片總數(shù)
const totalPieces = Math.ceil(filesize / bytesPerPiece);
while (index < totalPieces) {
start = index * bytesPerPiece;
//++index === totalPieces 最后一片
end = ++index === totalPieces ? filesize : index * bytesPerPiece;
const chunk = blob.slice(start, end); //切割文件
blobArray.push({
file: chunk,
name: `${blob.name}(${index})`,
type: blob.type,
});
}
return blobArray;
}
//模擬axios上傳
let _http = (data, ...config) => {
console.log(data);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data);
}, 200);
});
};
function sendblob (blobArray, num, totalSize) {
// totalSize用來計算總進度 progressObj存儲每一片的上傳進度
let progressObj = {};
//計算進度條
function computeProgress (key, loaded, total) {
progressObj[key] = {
loaded,
total,
issuccess: loaded === total,
key,
};
let progress = 0;
if (progressObj) {
for (key in progressObj) {
progress += progressObj[key].loaded;
}
}
if (totalSize > progress && progress > 0) {
return (progress / totalSize) * 100 + "%";
}
return "0%";
}
//遞歸上傳,每次五條,成功后繼續(xù)
function send (fncarray) {
return Promise.all(
fncarray.map((blob) =>
_http(blob, {
onUploadProgress: (progressEvent) => {
computeProgress(
blob.name,
progressEvent.loaded,
progressEvent.total
);
},
})
)
).then((list) => {
fileData = fileData.concat(list)
blobArray.splice(0, num);
if (blobArray.length > 0) {
send(blobArray.slice(0, num));
} else {
console.log('end');
}
});
}
send(blobArray.slice(0, num));
}
async function valid (file, accept) {
//根據(jù)文件頭驗證文件類型
if (!file instanceof Blob) {
throw Error("僅支持Blob驗證");
// return false
}
if (!accept) return;
const Ext2Hex = {
jpg: /^(ffd8ffe)[0-4]{1}/,
png: /^(89504e47){1}/,
ico: /^(100){1}/,
gif: /^(47494638){1}/,
};
let first4Byte = new DataView(await file.arrayBuffer()).getUint32(
0,
false
);
const uint32 = Number(first4Byte).toString(16);
return Object.keys(Ext2Hex).some((key) => {
if (accept.indexOf(key) > -1) {
return Ext2Hex[key].test(uint32);
}
});
}
function getFile (fileIds, num) {
let blobs = []
function getHttpFile (ids) {
return Promise.all(
ids.map((name) =>
_http(name, {
onUploadProgress: (progressEvent) => { },
}).then(name => {
return fileData.find(e => e.name === name)
})
)
).then(async (list) => {
blobs = blobs.concat(list)
fileIds.splice(0, 5);
if (fileIds.length > 0) {
await getHttpFile(fileIds.slice(0, 5))
} else {
console.log('end');
}
return blobs
});
}
return getHttpFile(fileIds.slice(0, 5))
}
//模擬分片下載
function download () {
// 調(diào)接口獲取文件信息,根據(jù)大小去判斷是否分片獲取
// 模擬直接使用上傳時賦值的 file
if (file.size > 10 * 1024) {
const fileIds = fileData.map(e => e.name);//fileIds 模擬file分割出的文檔碎片id/name
getFile(fileIds, 5).then(blobs => { //獲取文件碎片,每次發(fā)5條請求
const blob = new Blob(blobs.map(e => e.file), {
type: blobs[0].type
});
exprotStart(blob)
})
}
}
function exprotStart (blob, name) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = name || Date.now();;
link.click();
window.URL.revokeObjectURL(link.href);
}
</script>
</body>
</html>
切片上傳_根據(jù)文件頭判斷文件類型_分片合并下載
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- public enum FileType { JSP("3C25402070"), EXE("4D5A900003...
- 原理:二進制的前2位的ascii碼用來進行判斷文件類型 我的使用場景: 在WKWebView 加載的網(wǎng)頁中,點擊下...