欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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)文章

  • js實(shí)現(xiàn)3D輪播圖效果

    js實(shí)現(xiàn)3D輪播圖效果

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)3D輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Bootstrap基本組件學(xué)習(xí)筆記之進(jìn)度條(15)

    Bootstrap基本組件學(xué)習(xí)筆記之進(jìn)度條(15)

    這篇文章主要為大家詳細(xì)介紹了Bootstrap基本組件學(xué)習(xí)筆記之進(jìn)度條,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • JavaScript利用切片實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳

    JavaScript利用切片實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳

    斷點(diǎn)續(xù)傳即在文件上傳期間因?yàn)橐恍┰蚨鴮?dǎo)致上傳終止時(shí),下次再次上傳同一個(gè)文件就從上一次上傳到一半的地方繼續(xù)上傳,以節(jié)省上傳時(shí)間。本文將利用切片實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳功能,快來跟隨小編一起學(xué)一學(xué)吧
    2022-03-03
  • JavaScript30 一個(gè)月純 JS 挑戰(zhàn)中文指南(英文全集)

    JavaScript30 一個(gè)月純 JS 挑戰(zhàn)中文指南(英文全集)

    JavaScirpt30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 個(gè)視頻教程、30 個(gè)挑戰(zhàn)的起始文檔和 30 個(gè)挑戰(zhàn)解決方案源代碼。目的是幫助人們用純 JavaScript 來寫東西,不借助框架和庫,也不使用編譯器和引用
    2017-07-07
  • highlight.js 代碼高亮插件的使用詳解

    highlight.js 代碼高亮插件的使用詳解

    在網(wǎng)頁使用過程中,經(jīng)常會用到代碼的展示。代碼高亮可以直觀的了解代碼,本文主要介紹了highlight.js 代碼高亮插件的使用詳解,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-01-01
  • 用Webpack構(gòu)建Vue項(xiàng)目的實(shí)踐

    用Webpack構(gòu)建Vue項(xiàng)目的實(shí)踐

    這篇文章主要介紹了用Webpack構(gòu)建Vue項(xiàng)目的實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • D3.js實(shí)現(xiàn)簡潔實(shí)用的動(dòng)態(tài)儀表盤的示例

    D3.js實(shí)現(xiàn)簡潔實(shí)用的動(dòng)態(tài)儀表盤的示例

    本篇文章主要介紹了D3.js實(shí)現(xiàn)簡潔實(shí)用的動(dòng)態(tài)儀表盤的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • JavaScript前補(bǔ)零操作實(shí)例

    JavaScript前補(bǔ)零操作實(shí)例

    這篇文章主要介紹了JavaScript前補(bǔ)零操作的方法,以實(shí)例形式對比分析了javascript實(shí)現(xiàn)補(bǔ)零操作的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • Bootstrap模態(tài)對話框中顯示動(dòng)態(tài)內(nèi)容的方法

    Bootstrap模態(tài)對話框中顯示動(dòng)態(tài)內(nèi)容的方法

    今天小編就為大家分享一篇Bootstrap模態(tài)對話框中顯示動(dòng)態(tài)內(nèi)容的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • 用JS動(dòng)態(tài)改變表單form里的action值屬性的兩種方法

    用JS動(dòng)態(tài)改變表單form里的action值屬性的兩種方法

    下面小編就為大家?guī)硪黄肑S動(dòng)態(tài)改變表單form里的action值屬性的兩種方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-05-05

最新評論