2017-06-12 68 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