如何记录60MB以上的HTML5拖放文件的内容而不会挂起几分钟

How to log contents of HTML5 drag and drop file that is 60MB+ without hanging for minutes?

本文关键字:几分钟 挂起 分钟 HTML5 记录 何记录 60MB 拖放 文件      更新时间:2023-09-26

我有一个文件,我想在页面上放置并读取文件内容。它是一个9列的CSV文件。我的drop命令输出文件内容如下:

function drop(ev) {
    ev.preventDefault();
    var data  = ev.dataTransfer.files[0];
    var fileReader = new FileReader();
    fileReader.onload = function (e) {
        console.log(fileReader.result)
    };
    fileReader.onerror = function (e) {
        throw 'Error reading CSV file';
    };
    // Start reading file
    fileReader.readAsText(data);
    return false;    
}

当我拖放一个几千字节或1MB大小的简单文件时,我可以看到该文件内容的输出。然而,对于一个大的CSV文件,它需要很多很多分钟才能显示出来。有没有一种方法可以让它看起来不像挂着的那种流?

使用螺旋文件阅读器你可以获得一个ReadableStream,并以流方式执行它

'use strict'
var blob = new Blob(['111,222,333'naaa,bbb,ccc']) // simulate a file
var stream = blob.stream()
var reader = stream.getReader()
var headerString = ''
var forEachLine = function(row) {
  var colums = row.split(',')
    // append to DOM
  console.log(colums)
}
var pump = function() {
  return reader.read().then(function(result) {
    var value = result.value
    var done = result.done
    if (done) {
      // Do the last line
      headerString && forEachLine(headerString)
      return
    }
    for (var i = 0; i < value.length; i++) {
      // Get the character for the current iteration
      var char = String.fromCharCode(value[i])
      // Check if the char is a new line
      if (char.match(/[^'r'n]+/g) !== null) {
        // Not a new line so lets append it to
        // our header string and keep processing
        headerString += char
      } else {
        // We found a new line character
        forEachLine(headerString)
        headerString = ''
      }
    }
    return pump()
  })
}
pump().then(function() {
  console.log('done reading the csv')
})
<script src="https://cdn.rawgit.com/jimmywarting/Screw-FileReader/master/index.js"></script>

如果你更喜欢使用旧的没有依赖的FileReader, pipe's和transform

'use strict'
var blob = new Blob(['111,222,333'naaa,bbb,ccc']) // simulate a file
var fr = new FileReader()
var headerString = ''
var position = 0
var forEachLine = function forEachLine(row) {
  var colums = row.split(',')
    // append to DOM
  console.log(colums)
}
var pump = function pump() {
  return new Promise(function(resolve) {
    var chunk = blob.slice(position, position + 524288)
    position += 524288
    fr.onload = function() {
      var value = fr.result
      var done = position >= blob.size
      for (var i = 0; i < value.length; i++) {
        var char = value[i]
        // Check if the char is a new line
        if (char.match(/[^'r'n]+/g) !== null) {
          // Not a new line so lets append it to
          // our header string and keep processing
          headerString += char
        } else {
          // We found a new line character
          forEachLine(headerString)
          headerString = ''
        }
      }
      if (done) {
        // Send the last line
        forEachLine(headerString)
        return resolve() // done
      }
      return resolve(pump())
    }
    // Read the next chunk
    fr.readAsText(chunk)
  })
}
pump().then(function() {
  console.log('done reading the csv')
})