html
然后来编写 html ,这没有什么好说的,写两个按钮来展示。
串行下载
多线程下载
js公共参数
const m = 1024 * 520; // 分片的大小
const url = ‘http://localhost:8888/api/rangeFile?filename=360_0388.jpg’; // 要下载的地址
单线程部分
单线程下载代码,直接去请求以blob
方式获取,然后用blobURL
的方式下载。
download1.onclick = () => {
console.time(“直接下载”);
function download(url) {
const req = new XMLHttpRequest();
req.open(“GET”, url, true);
req.responseType = “blob”;
req.onload = function (oEvent) {
const content = req.response;
const aTag = document.createElement(‘a’);
aTag.download = ‘360_0388.jpg’;
const blob = new Blob([content])
const blobUrl = URL.createObjectURL(blob);
aTag.href = blobUrl;
aTag.click();
URL.revokeObjectURL(blob);
console.timeEnd(“直接下载”);
};
req.send();
}
download(url);
}
多线程部分
首先发送一个 head 请求,来获取文件的大小,然后根据 length 以及设置的分片大小,来计算每个分片是滑动距离。通过Promise.all
的回调中,用concatenate
函数对分片 buffer 进行一个合并成一个 blob,然后用blobURL
的方式下载。
// script
function downloadRange(url, start, end, i) {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open(“GET”, url, true);
req.setRequestHeader(‘range’, bytes=${start}-${end}
)
req.responseType = “blob”;
req.onload = function (oEvent) {
req.response.arrayBuffer().then(res => {
resolve({
i,
buffer: res
});
})
};
req.send();
})
}
// 合并buffer
function concatenate(resultConstructor, arrays) {
let totalLength = 0;
for (let arr of arrays) {
totalLength += arr.length;
}
let result = new resultConstructor(totalLength);
let offset = 0;
for (let arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
}
download2.onclick = () => {
axios({
url,
method: ‘head’,
}).then((res) => {
// 获取长度来进行分割块
console.time(“并发下载”);
const size = Number(res.headers[‘content-length’]);
const length = parseInt(size / m);
const arr = []
for (let i = 0; i < length; i++) {
let start = i * m;
let end = (i == length - 1) ? size - 1 : (i + 1) * m - 1;
arr.push(downloadRange(url, start, end, i))
}
Promise.all(arr).then(res => {
const arrBufferList = res.sort(item => item.i - item.i).map(item => new Uint8Array(item.buffer));
const allBuffer = concatenate(Uint8Array, arrBufferList);
const blob = new Blob([allBuffer], {type: ‘image/jpeg’});