2017-06-12 98 views
0

因此,這裏是我的問題: 我有一個大型的文本文件(大小約150 MB),數十萬行。我需要讀取文件的內容,解析它以便將這些行放入適當的html標記中並將其寫入window.document.open()對象中。使用AJAX + Javascript以塊讀取文件

我的代碼適用於文件,直到50 MB的大小。

var rawFile=new XMLHttpRequest(); 
    rawFile.open("GET",file, true); 
    rawFile.onreadystatechange= function() { 
     if (rawFile.readyState === 4) { 
      if (rawFile.status === 200 || rawFile.status === 0) { 
       var allText = rawFile.responseText; 
       var contents = allText.split("\n"); 
       var w = window.open(); 
       w.document.open(); 
       for (i = 0; i < contents.length; i++) { 
        //logc so that str= appropriate tags + contents[i] 
        w.document.write(str); 
       } 
      } 
     } 
    } 

該代碼有效。邏輯起作用。 但是,如果文件大小大於100MB或類似,Chrome會崩潰。 我認爲以大塊讀取文件,然後將其寫入window.document.open()將爲我解決這個問題。

任何意見,我怎麼可能去實現這一點是非常讚賞。 謝謝:)

(忽略是否有我上面貼的代碼的任何錯誤,我實際的代碼是非常大的,所以我只是寫它的一個微縮版)

+0

檢查[這](http://www.plupload.com/) –

+0

有沒有辦法,我可以用普通的JavaScript/jQuery的做到這一點,而無需使用任何插件? – Vamshi

+0

當然有。自己創建整個插件。重新發明輪子。哈哈。 –

回答

1

你的做法將削弱,因爲瀏覽器您正在處理整個響應。更好的方法是將流程分解,以便處理更小的塊,或者通過流程將文件流式傳輸。

使用Fetch API而不是XMLHttpRequest可讓您訪問流數據。使用流的最大優勢在於,您在處理內容時不會佔用瀏覽器的內存。

下面的代碼概述瞭如何使用流來執行任務:

var file_url = 'URL_TO_FILE'; 
// @link https://developer.mozilla.org/en-US/docs/Web/API/Request/Request 
var myRequest = new Request(file_url); 
// fetch returns a promise 
fetch(myRequest) 
    .then(function(response) { 
    var contentLength = response.headers.get('Content-Length'); 
    // response.body is a readable stream 
    // @link https://docs.microsoft.com/en-us/microsoft-edge/dev-guide/performance/streams-api 
    var myReader = response.body.getReader(); 
    // the reader result will need to be decoded to text 
    // @link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/TextDecoder 
    var decoder = new TextDecoder(); 
    // add decoded text to buffer for decoding 
    var buffer = ''; 
    // you could use the number of bytes received to implement a progress indicator 
    var received = 0; 
    // read() returns a promise 
    myReader.read().then(function processResult(result) { 
     // the result object contains two properties: 
     // done - true if the stream is finished 
     // value - the data 
     if (result.done) { 
     return; 
     } 
     // update the number of bytes received total 
     received += result.value.length; 
     // result.value is a Uint8Array so it will need to be decoded 
     // buffer the decoded text before processing it 
     buffer += decoder.decode(result.value, {stream: true}); 
     /* process the buffer string */ 

     // read the next piece of the stream and process the result 
     return myReader.read().then(processResult); 
    }) 
    }) 

我並沒有實現用於處理緩衝的代碼,但該算法將如下所示:

If the buffer contains a newline character: 
    Split the buffer into an array of lines 
If there is still more data to read: 
    Save the last array item because it may be an incomplete line 
    Do this by setting the content of the buffer to that of the last array item 
Process each line in the array 

快速瀏覽Can I Use告訴我,這在IE中不起作用,因爲Fetch API在Edge瀏覽器之前未實現。然而,沒有必要絕望,因爲一如既往的某種靈魂已經爲不支持的瀏覽器實現了polyfill

+0

非常感謝! 我會試試這個並回復你:) – Vamshi

+0

嗨! 所以我試着做你所提到的。我仍然有這個問題。我正在處理一個巨大的文件(超過150萬行),當我處理緩衝區並寫入一個新窗口時,腳本完成執行(比我原來的更好),但我仍然收到消息說「該頁面有變得沒有反應,等待或殺死「。 Chrome瀏覽器不會崩潰,但我仍然無法獲得我想要的內容,因爲該頁面無響應。 這是因爲我超過了Chrome默認的內存限制嗎? – Vamshi

+0

更新:現在我在顯示此網頁時遇到內存不足。 任何解決此問題的方法? – Vamshi