如何从JS中的ArrayBuffer编写文件

Kar*_*l.S 14 javascript file-upload node.js arraybuffer meteor

我正在尝试为Meteor框架编写一个文件上传器.原理是将客户端上的文件从ArrayBuffer拆分为4096位的小包,通过Meteor.method发送到服务器.

下面简化的代码是客户端向服务器发送一个块的部分,它会重复,直到offset到达data.byteLength:

// data is an ArrayBuffer
var total = data.byteLength;
var offset = 0;

var upload = function() {
  var length = 4096; // chunk size

  // adjust the last chunk size
  if (offset + length > total) {
     length = total - offset;
  }

  // I am using Uint8Array to create the chunk
  // because it can be passed to the Meteor.method natively
  var chunk = new Uint8Array(data, offset, length);

  if (offset < total) {
     // Send the chunk to the server and tell it what file to append to
     Meteor.call('uploadFileData', fileId, chunk, function (err, length) {
        if (!err) {
          offset += length;
          upload();
        }
     }
  }
};
upload(); // start uploading
Run Code Online (Sandbox Code Playgroud)

下面简化的代码是服务器上接收块并将其写入文件系统的部分:

var fs = Npm.require('fs');
var Future = Npm.require('fibers/future');

Meteor.methods({
  uploadFileData: function(fileId, chunk) {
    var fut = new Future();
    var path = '/uploads/' + fileId;

    // I tried that with no success
    chunk = String.fromCharCode.apply(null, chunk);

    // how to write the chunk that is an Uint8Array to the disk ?
    fs.appendFile(path, chunk, 'binary', function (err) {
      if (err) {
        fut.throw(err);
      } else {
        fut.return(chunk.length);
      }
    });
    return fut.wait();
  }
});
Run Code Online (Sandbox Code Playgroud)

我没有写一个有效的文件到磁盘,实际上文件已保存,但我无法打开它,当我在文本编辑器中看到内容时,它类似于原始文件(例如jpg)但有些字符不同,我认为这可能是一个编码问题,因为文件大小不一样,但我不知道如何修复...

Kar*_*l.S 17

保存文件就像使用Uint8Array对象创建新缓冲区一样简单:

// chunk is the Uint8Array object
fs.appendFile(path, new Buffer(chunk), function (err) {
    if (err) {
      fut.throw(err);
    } else {
      fut.return(chunk.length);
    }
});
Run Code Online (Sandbox Code Playgroud)

  • new Buffer(chunk) 已弃用,使用 Buffer.from(chunk) (5认同)

tom*_*oms 9

Karl.S回答的基础上,除了任何框架之外,这对我有用:

fs.appendFileSync(outfile, new Buffer(arrayBuffer));
Run Code Online (Sandbox Code Playgroud)

  • 新的缓冲区已被弃用。使用 Buffer.from(arrayBuffer) 代替。 (10认同)
  • 不建议使用 I/O 函数的同步版本,因为它会阻止事件循环,除非您有理由这样做。 (2认同)