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

深入解析Nodejs中的大文件讀寫

 更新時間:2022年09月28日 08:48:38   作者:yuxiaoliang???????  
這篇文章主要介紹了深入解析Nodejs中的大文件讀寫,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下

前言

最近在做一些node端的文件讀寫和分片上傳工作,在這個過程中,發(fā)現(xiàn)node讀取的文件如果超過2G,超過了讀取Blob最大值,會出現(xiàn)讀取異常,此外在node中讀寫文件也受服務(wù)器RAM的限制等,需要分片讀取,本人記錄一下遇到的問題以及解決問題的經(jīng)過。

  • node中的文件讀寫
  • node文件讀寫RAM和Blob大小的限制
  • 其他

官網(wǎng)

一、node中的文件讀寫

1.1 常規(guī)文件讀寫

常規(guī)的,如果我們要讀取一個比較小的文件,可以直接通過:

const fs = require('fs')
let data = fs.readFileSync("./test.png")
console.log(data,123)
//輸出data = <Buffer 89 50 4e ...>

 一般而言,同步的方法不是很推薦,因為js/nodejs是單線程的,同步的方法會阻塞主線程。最新版的node直接提供了fs.promise,可以結(jié)合async/await直接使用:

const fs = require('fs')
const readFileSync = async () => {
    let data = await fs.promises.readFile("./test.png")
    console.log(data,123)
}
readFileSync()
//輸出data = <Buffer 89 50 4e ...>

這里通過異步的方法調(diào)用不會阻塞主線程,多個文件讀取的IO也可以并行進(jìn)行等。

1.2 Stream文件讀寫

常規(guī)的文件讀寫,我們會把文件一次性的讀取到內(nèi)存中,這種方法時間效率和內(nèi)存效率都很低,時間效率低是指必須要一次性讀取完畢后才能執(zhí)行后續(xù)才做,內(nèi)存效率低是指必須把這個文件都一次性讀取放入內(nèi)存中,很占用內(nèi)存。

因此這種情況下,我們一般使用Stream來進(jìn)行文件的讀?。?/strong>

const fs = require('fs')
const readFileTest = () => {
    var data = ''
    var rs = fs.createReadStream('./test.png');
    rs.on('data', function(chunk) {
        data += chunk;
        console.log(chunk)
     });
    rs.on('end',function(){
        console.log(data);
    });
    rs.on('error', function(err){
        console.log(err.stack);
     });
}
readFileTest()
// data = <Buffer 89 50 64 ...>

通過Steam來進(jìn)行文件讀寫,可以提高內(nèi)存效率和時間效率。

  • 內(nèi)存效率:在處理數(shù)據(jù)之前,不需要在內(nèi)存中加載大量(或整個)數(shù)據(jù)
  • 時間效率:一旦有了數(shù)據(jù),就可以開始處理,這大大減少開始處理數(shù)據(jù)的時間,而不必等到整個數(shù)據(jù)加載完畢再進(jìn)行處理。

Stream的文件還支持第二種寫法:

const fs = require('fs')
const readFileTest = () => {
    var data = ''
    var chunk;
    var rs = fs.createReadStream('./test.png');
    rs.on('readable', function() {
    while ((chunk=rs.read()) != null) {
        data += chunk;
    }});
    rs.on('end', function() {
        console.log(data)
    });
};
readFileTest()

二、node文件讀寫RAM和Blob大小的限制

2.1 基礎(chǔ)問題

在讀取大文件時,會有讀取文件大小的限制,比如我們現(xiàn)在在讀取一個2.5G的視頻文件:

const fs = require('fs')
const readFileTest = async () => {
    let data = await fs.promises.readFile("./video.mp4")
    console.log(data)
}
readFileTest()

執(zhí)行上述的代碼會報錯:

RangeError [ERR_FS_FILE_TOO_LARGE]: File size (2246121911) is greater than 2 GB

 我們可能會想到,通過設(shè)置option,NODE_OPTIONS='--max-old-space-size=5000',此時5000M>2.5G,但是報錯還是沒有消失,也就是說通過Options無法改變node讀取文件的大小限制。

上述是常規(guī)的方式讀取大文件,如果通過Steam的方式讀取還會有文件大小的限制嘛? 比如:

const fs = require('fs')
const readFileTest = () => {
    var data = ''
    var rs = fs.createReadStream('./video.mp4');
    rs.on('data', function(chunk) {
        data += chunk;
     });
    rs.on('end',function(){
        console.log(data);
    });
    rs.on('error', function(err){
        console.log(err.stack);
     });
}
readFileTest()

如上方式讀取一個2.5G的文件不會有異常,不過要注意的是這邊有一個報錯:

data += chunk;
                ^
RangeError: Invalid string length

此時是因為data的長度超過了最大限制,比如2048M等。因此在用Steam處理的時候,在對讀取結(jié)果的保存時,要注意文件的大小,千萬不能超過默認(rèn)的Buffer的最大值。上述這種情況,我們不用data += chunk將數(shù)據(jù)全部保存在一個大的data中,我們可以邊讀取邊處理。

2.2 分片讀取

createReadStream在讀取文件的過程中,其實也可以分段讀取,這種分段讀取的方法也可以做為大文件讀取的備選項。特別是在并發(fā)讀取的時候有一定的優(yōu)點,可以提升文件讀取和處理的速度。

createReadStream接受第二個參數(shù){start,end}。我們可以通過fs.promises.stat來獲取文件的大小,然后確定分片,最后分片一次讀取,比如:

  • 獲取文件大小
const info = await fs.promises.stat(filepath)
   const size = info.size
  • 按照指定的SIZE分片(比如128M一個分片)
  const SIZE = 128 * 1024 * 1024
  let sizeLen = Math.floor(size/SIZE)
    let total = sizeLen +1 ;
    for(let i=0;i<=sizeLen;i++){
      if(sizeLen ===i){
        console.log(i*SIZE,size,total,123)
        readStremfunc(i*SIZE,size,total)
      }else{
        console.log(i*SIZE,(i+1)*SIZE,total,456)
        readStremfunc(i*SIZE,(i+1)*SIZE-1,total)
      }
    }
  //分片后【0,128M】,【128M, 256M】...

3.實現(xiàn)讀取函數(shù)

const readStremfunc = () => {
    const readStream =  fs.createReadStream(filepath,{start:start,end:end})
    readStream.setEncoding('binary')
    let data = ''
    readStream.on('data', chunk => {
        data = data + chunk
    })
    readStream.end('data', () => {
      ...
    })
}

    值得注意的是fs.createReadStream(filepath,{start,end}),start和end是前閉后閉的,比如fs.createReadSteam(filepath,{start:0,end:1023})讀取的是[0,1023]一共1024個bit。

三、其他

3.1 擴(kuò)展瀏覽器端的大文件讀寫、

前面將了大文件在nodejs中的讀取,那么在瀏覽器端會讀取大文件會有什么問題嗎?

 瀏覽器在本地讀取大文件時,之前有類似FileSaver、StreamSaver等方案,不過在瀏覽器本身添加了File的規(guī)范,使得瀏覽器本身就默認(rèn)和優(yōu)化了Stream的讀取。我們不需要做額外的工作,不過不同的版本會有兼容性的問題,我們還是可以通過FileSaver等進(jìn)行兼容。

3.2 請求靜態(tài)資源大文件

如果是在瀏覽器中獲取靜態(tài)資源大文件,一般情況下只需要通過range分配請求即可,一般的CDN加速域名,不管是阿里云還是騰訊云,對于分片請求都支持的很好,我們可以將資源通過cdn加速,然后在瀏覽器端直接請求cdn加速有的資源。

分片獲取cdn靜態(tài)資源大文件的步驟為,首先通過head請求獲取文件大?。?/strong>

const getHeaderInfo = async (url: string) => {
  const res: any = await axios.head(url + `?${Math.random()}`);
  return res?.headers;
};
const header = getHeaderInfo(source_url)
const size = header['content-length']

我們可以從header中的content-length屬性中,獲取文件的大小。

然后進(jìn)行分片和分段,最后發(fā)起range請求:

const getRangeInfo = async (url: string, start: number, end: number) => {
    const data = await axios({
      method: 'get',
      url,
      headers: {
        range: `bytes=${start}-${end}`,
      },
      responseType: 'blob',
    });
    return data?.data;
  };

在headers中指定 range: bytes=${start}-${end},就可以發(fā)起分片請求去獲取分段資源,這里的start和end也是前閉后閉的。

到此這篇關(guān)于深入解析Nodejs中的大文件讀寫的文章就介紹到這了,更多相關(guān)Nodejs大文件讀寫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Express框架之connect-flash詳解

    Express框架之connect-flash詳解

    本篇文章主要介紹了Express框架之connect-flash詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • npm安裝報錯npm ERR! Error: EPERM: operation not permitted解決

    npm安裝報錯npm ERR! Error: EPERM: operation&

    這篇文章主要為大家介紹了npm安裝報錯npm ERR! Error: EPERM: operation not permitted解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 利用n 升級工具升級Node.js版本及在mac環(huán)境下的坑

    利用n 升級工具升級Node.js版本及在mac環(huán)境下的坑

    這篇文章主要介紹了利用n 升級工具升級Node.js的方法,以及通過網(wǎng)友的測試發(fā)現(xiàn)在mac環(huán)境下利用n工具升級不成功導(dǎo)致node.js不可用的解決方法,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • 如何將Node.js中的回調(diào)轉(zhuǎn)換為Promise

    如何將Node.js中的回調(diào)轉(zhuǎn)換為Promise

    這篇文章主要給大家介紹了關(guān)于如何將Node.js中的回調(diào)轉(zhuǎn)換為Promise的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 在CentOS 7服務(wù)器上安裝Node.js的方法步驟

    在CentOS 7服務(wù)器上安裝Node.js的方法步驟

    Node.js 是一個用于服務(wù)器端編程的 JavaScript 平臺,允許用戶快速構(gòu)建網(wǎng)絡(luò)應(yīng)用程序,通過在前端和后端都使用 JavaScript,開發(fā)可以更加一致并且可以在同一個系統(tǒng)中設(shè)計,在本指南中,我們將向您展示如何在 Ubuntu 14.04 服務(wù)器上開始使用 Node.js
    2024-09-09
  • node.js將MongoDB數(shù)據(jù)同步到MySQL的步驟

    node.js將MongoDB數(shù)據(jù)同步到MySQL的步驟

    這篇文章主要給大家介紹了關(guān)于node.js將MongoDB數(shù)據(jù)同步到MySQL的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • Node.js利用斷言模塊assert進(jìn)行單元測試的方法

    Node.js利用斷言模塊assert進(jìn)行單元測試的方法

    最近在用Node寫一個實時聊天小應(yīng)用,其中就用到了單元測試,所以死下面這篇文章主要給大家介紹了關(guān)于Node.js利用斷言模塊assert進(jìn)行單元測試的方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Node.js讀寫文件之批量替換圖片的實現(xiàn)方法

    Node.js讀寫文件之批量替換圖片的實現(xiàn)方法

    下面小編就為大家?guī)硪黄狽ode.js讀寫文件之批量替換圖片的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • node+axios實現(xiàn)服務(wù)端文件上傳示例

    node+axios實現(xiàn)服務(wù)端文件上傳示例

    這篇文章主要介紹了node+axios實現(xiàn)服務(wù)端文件上傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Mac下安裝node.js及環(huán)境配置全過程

    Mac下安裝node.js及環(huán)境配置全過程

    這篇文章主要介紹了Mac下安裝node.js及環(huán)境配置全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05

最新評論