在Firefox中访问FileReader的部分结果 [英] Accessing partial results of a FileReader in Firefox

查看:91
本文介绍了在Firefox中访问FileReader的部分结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 FileReader 在我的Web应用程序中部分加载CSV文件到浏览器中.但是,我无法在Firefox 27中访问部分结果.

我的应用程序仅需要CSV文件的前100k字节来填充数据预览.因此,我先设置,启动,然后 中止 读取了一定数量的数据后的读取器.

以下是在Chrome 35中正常运行的示例:

  warn =(a ...)->警告...readFile =(file,cb,limit = 1e5)->警告开始读取文件..."fr =新的FileReader结果=空完成=->cb null,result [.. limit]复制=(e)->如果e.target.result?然后结果= e.target.result;警告已复制#{result.length}个字节"否则警告结果为空"fr.onloadstart =(e)->警告在本地读取#{file.name} ..."fr.onloadend =(e)->警告阅读结束(结束)";复制(e);完毕()fr.onabort =(e)->警告阅读结束(中止)";复制(e)fr.onload =(e)->警告读取完成(加载)";复制(e)fr.onprogress =(e)->警告进度..";复制(e)如果已加载>限制警告读取CSV文件的#{e.loaded}个字节以进行数据预览.中止FileReader."fr.abort();fr.onprogress =空fr.readAsText文件 

但是,该代码在Firefox中不起作用;中止阅读器时,所有复制的结果均为空.即使 progress 事件表明,除 null 外,所有事件 e 都没有携带 e.target.result .正确地设置了 e.loaded ,因此已经读取了一些数据,因此也按预期触发了 abort().

很明显,Chrome和Firefox似乎以不同的方式实现File API,即,以不同的方式处理 abort().在Firefox中,您始终必须完全加载文件才能获得任何结果.对我来说,这是不合适的,因为我的CSV文件具有200MB或更多字节的数据,因此在必须完全加载数据时,我的浏览器处于冻结状态.

PS:我只关心Chrome和FF.IE和移动超出了该项目的范围

编辑:以下是在Chrome和Firefox中运行良好的最终解决方案:

  readFile =(file,cb,limit = 1e4)->警告开始读取文件..."fr =新的FileReader完成=(e)->警告读取#{e.loaded}的CSV文件的#{file.size}字节以进行数据预览"cb null,fr.resultfr.onloadstart =(e)->警告在本地读取#{file.name} ..."fr.onload =(e)->警告读取完成(加载)";完成(e)fr.readAsText file.slice 0,限制 

解决方案

Chrome违反了当前规范草案,其中规定了 abort():

如果readyState = LOADING,请将readyState设置为DONE并将结果设置为null .((,重点是我的)

现在,您可以争论这是好事还是坏事...

仅读取部分文件的最佳方法是 .slice() 文件/Blob对象,然后再将其传递给阅读器,告诉浏览器首先只读取文件的一部分:

  fr.readAsText(file.slice(0,limit)); 

当然,在处理多字节编码(例如UTF-8)时,您可能不得不处理问题.但是,无论如何,即使是仅使用Chrome的 abort()的东西.

I want to use a FileReader in my web application to partially load a CSV file into the browser. However, I am not able to access partial results in Firefox 27.

My application requires only the first 100k bytes of the CSV file to populate a data preview. Therefore, I setup, start, and then abort the reader after a certain amount of data has been loaded.

Here is an example that works fine in Chrome 35:

  warn = (a...) -> console.warn a...
  readFile = (file,cb,limit=1e5) ->
    warn "start reading file..."
    fr = new FileReader
    result = null
    done = -> cb null,result[..limit]
    copy = (e) ->
      if e.target.result? then result = e.target.result; warn "copied #{result.length} bytes"
      else warn "result is empty"
    fr.onloadstart = (e) -> warn "Reading #{file.name} locally..."
    fr.onloadend   = (e) -> warn "Reading finished (end)";   copy(e); done()
    fr.onabort     = (e) -> warn "Reading finished (abort)"; copy(e)
    fr.onload      = (e) -> warn "Reading finished (load)";  copy(e)
    fr.onprogress  = (e) ->
      warn "progress.."; copy(e)
      if e.loaded > limit
        warn "Read #{e.loaded} bytes of CSV file for data preview. Aborting FileReader."
        fr.abort(); fr.onprogress = null
    fr.readAsText file

However, the code does not work in Firefox; all copied results are empty when aborting the reader. None of the events e carries an e.target.result other than null, even if the progress event indicates that some data has been read, as e.loaded is set correctly and thus the abort() is also triggered as expected.

Obviously Chrome and Firefox seem to implement the File API differently, i.e., handle the abort() differently. In Firefox you always have to fully load a file to get any result. For me this is not suitable, since my CSV files have 200MB or more bytes of data, leaving me with a frozen browser when having to load the data completely.

PS: I only care for Chrome and FF. IE and mobile are out of scope for this project

EDIT: Here is the final solution that works nicely in Chrome and Firefox:

  readFile = (file,cb,limit=1e4) ->
    warn "start reading file..."
    fr = new FileReader
    done = (e) ->
      warn "Read #{e.loaded} of #{file.size} bytes of CSV file for data preview"
      cb null,fr.result
    fr.onloadstart = (e) -> warn "Reading #{file.name} locally..."
    fr.onload      = (e) -> warn "Reading finished (load)"; done(e)
    fr.readAsText file.slice 0,limit

解决方案

Chrome violates the current spec draft which states for abort():

If readyState = LOADING set readyState to DONE and result to null. (source, emphasis mine)

Now, you can argue whether this is a good or bad thing to do...

The best way to read only part of the file is to .slice() the File/Blob object before passing it to the reader, telling the browser to read only part of the file in the first place:

fr.readAsText(file.slice(0, limit));

Of course, you might have to deal with issues when processing multi-byte encodings such as UTF-8... But you'd have to deal with that anyway, even with your Chrome-only abort() stuff.

这篇关于在Firefox中访问FileReader的部分结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆