最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

js分片下載超出2G的大文件代碼實(shí)例

 更新時(shí)間:2024年04月19日 10:39:06   作者:SmallFatMan  
為了實(shí)現(xiàn)斷點(diǎn)續(xù)傳,研究了js的文件分片,下面這篇文章主要給大家介紹了關(guān)于js分片下載超出2G的大文件的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

思路

針對超過2G的大文件,通常需要將文件進(jìn)行分塊下載,以避免瀏覽器的內(nèi)存溢出或者因?yàn)榫W(wǎng)絡(luò)連接不穩(wěn)定而導(dǎo)致整個(gè)下載失敗的情況。

下面是一個(gè)基本的分塊下載的代碼樣例:

async downloadFile(url, fileName) {
    const CHUNK_SIZE = 1024 * 1024 * 10 // 每次下載10MB
    const response = await fetch(url)
    const contentRange = response.headers.get('content-range') 
    const fileSize = contentRange ? Number(contentRange.split('/')[1]) : response.headers.get('content-length')
    const fileStream = []
    let offset = 0

    while (offset < fileSize) {
        const end = Math.min(offset + CHUNK_SIZE, fileSize)
        const options = {
            headers: { 'Range': `bytes=${offset}-${end - 1}` }
        }
        const blob = await fetch(url, options).then(res => res.blob())
        fileStream.push(blob)
        offset = end
    }

    const blob = new Blob(fileStream, { type: response.headers.get('content-type') })
    saveAs(blob, fileName)
}

解釋

這段代碼使用了Fetch API來下載文件,同時(shí)使用了Range頭來告訴服務(wù)器只需要下載文件的一部分。將文件大小分割為塊,每次下載一塊數(shù)據(jù),最后將數(shù)據(jù)組合成一個(gè)Blob對象進(jìn)行下載。需要注意的是,如果下載的文件有Content-Range頭,則需要先從這個(gè)頭里獲取文件總大小。

async downloadFile(url, fileName) {
  • 這段代碼是一個(gè)異步函數(shù),用于從給定的URL下載大文件,并使用blob對象保存文件。
  • 該函數(shù)需要傳入兩個(gè)參數(shù),一個(gè)是要下載的文件的url,另外一個(gè)則是下載后要保存的文件名。
const CHUNK_SIZE = 1024 * 1024 * 10 // 每次下載10MB
  • 為了避免下載整個(gè)文件的時(shí)候因?yàn)閮?nèi)存不足而導(dǎo)致的錯(cuò)誤,把文件劃分成了多個(gè)大小相等的塊,每次下載一個(gè)塊的數(shù)據(jù)。這里設(shè)置每次下載的塊為10MB。
const response = await fetch(url)
const contentRange = response.headers.get('content-range') 
const fileSize = contentRange ? Number(contentRange.split('/')[1]) : response.headers.get('content-length')
  • 使用Fetch API向服務(wù)器請求數(shù)據(jù)。從響應(yīng)頭里獲取了Content-Range,這個(gè)頭可以告訴服務(wù)器只需要下載文件的一部分。如果不存在Content-Range頭,那么就通過response.headers.get(‘content-length’)獲取文件的總大小。
const fileStream = []
let offset = 0

while (offset < fileSize) {
    const end = Math.min(offset + CHUNK_SIZE, fileSize)
    const options = {
        headers: { 'Range': `bytes=${offset}-${end - 1}` }
    }
    const blob = await fetch(url, options).then(res => res.blob())
    fileStream.push(blob)
    offset = end
}
  • 使用一個(gè)while循環(huán)將整個(gè)文件分塊下載,每次下載一塊數(shù)據(jù)。
  • 循環(huán)中定義了兩個(gè)變量:一個(gè)是fileStream,用于保存從服務(wù)器下載的每個(gè)塊;另一個(gè)則是offset,表示已經(jīng)下載的數(shù)據(jù)大小。
  • 在每次循環(huán)開始時(shí),首先計(jì)算本次下載的起點(diǎn)和終點(diǎn),然后構(gòu)造一個(gè)包含Range頭的選項(xiàng)對象。將起點(diǎn)和終點(diǎn)放在Range頭里,這樣服務(wù)器就只會返回指定范圍的數(shù)據(jù)。最后,使用Fetch API向服務(wù)器請求數(shù)據(jù),并將用于保存數(shù)據(jù)的Blob對象推入fileStream數(shù)組中。
  • 最后,更新offset的值,表示已經(jīng)下載的總大小。
const blob = new Blob(fileStream, { type: response.headers.get('content-type') })
saveAs(blob, fileName)
  • 在while循環(huán)結(jié)束后,將fileStream數(shù)組中的所有Blob對象合并為一個(gè)Blob對象,并使用FileSaver.js的saveAs函數(shù)來將其保存在本地磁盤上。
  • 需要注意的是,在Blob的構(gòu)造函數(shù)中傳入了response.headers.get(‘content-type’),這是由于下載的文件類型不一定是常規(guī)的文件類型,所以我們需要從響應(yīng)頭中獲取正確的文件類型。
  • 以上就是該函數(shù)的所有內(nèi)容,它通過將文件劃分為多個(gè)塊,避免了下載整個(gè)大文件時(shí)可能導(dǎo)致的內(nèi)存溢出等問題,并且沒有在瀏覽器中產(chǎn)生任何嚴(yán)重的內(nèi)存或性能問題。

附:javascript 大文件下載,分片下載,斷點(diǎn)續(xù)傳

// status
const DONE = 4;

// range size
const RANGE_SIZE = 100;

// get content length
function getContentLength(url) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.open('HEAD', url, true);
        xhr.onreadystatechange = function () {
            if (this.readyState == DONE) {
                resolve(this.getResponseHeader('Content-Length'));
            }
        }
        xhr.send();
    })
}

// get range content
function getRangeContent(startIndex, endIndex, url) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.setRequestHeader('Range', `bytes=${startIndex}-${endIndex}`);
        xhr.responseType = 'arraybuffer';
        xhr.onreadystatechange = function () {
            if (this.readyState == DONE) {
                console.log(this.response)
                resolve(this.response);
            }
        }
        xhr.send();
    })
}

// download arraybuffer file
function downloadArrayBufferFile(arrayBuffer, fileName) {
    const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = fileName;
    a.click();
}

// concat arraybuffer array
function concatArrayBuffer(arrayBufferArray) {
    let totalLength = 0;
    arrayBufferArray.forEach(arrayBuffer => {
        totalLength += arrayBuffer.byteLength;
    });
    const result = new Uint8Array(totalLength);
    let offset = 0;
    arrayBufferArray.forEach(arrayBuffer => {
        result.set(new Uint8Array(arrayBuffer), offset);
        offset += arrayBuffer.byteLength;
    });
    return result;
}

// main methoeds
async function main() {
    const fileUrl = 'http://localhost:8083/public/access.txt';
    const contentLength = await getContentLength(fileUrl);
    const numberRequest = Math.ceil(contentLength / RANGE_SIZE);
    const arrayBufferArray = [];
    for (let i = 0; i < numberRequest; i++) {
        const startIndex = i * RANGE_SIZE;
        const endIndex = startIndex + RANGE_SIZE - 1;
        const clip = await getRangeContent(startIndex, endIndex, fileUrl);
        arrayBufferArray.push(clip);
    }
    const result = concatArrayBuffer(arrayBufferArray);
    downloadArrayBufferFile(result, 'access.txt');
}

main();

總結(jié) 

到此這篇關(guān)于js分片下載超出2G大文件的文章就介紹到這了,更多相關(guān)js分片下載超2G大文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

皋兰县| 衡东县| 长白| 深水埗区| 天津市| 临武县| 大竹县| 屯留县| 五指山市| 山丹县| 凤山市| 香河县| 蓬莱市| 宁德市| 巴林左旗| 鄂尔多斯市| 台山市| 京山县| 定陶县| 和林格尔县| 南昌市| 扎兰屯市| 锡林郭勒盟| 绥宁县| 陈巴尔虎旗| 安康市| 铅山县| 城步| 舞阳县| 徐州市| 黄大仙区| 蓬溪县| 穆棱市| 三原县| 新野县| 礼泉县| 庄河市| 湖北省| 久治县| 法库县| 隆子县|