Accessing partial results of a FileReader in Firefox

♀尐吖头ヾ 提交于 2021-01-28 11:55:57

问题


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

回答1:


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.



来源:https://stackoverflow.com/questions/24809960/accessing-partial-results-of-a-filereader-in-firefox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!