简体   繁体   English

如何从JS中的ArrayBuffer写入文件

[英]How to write a file from an ArrayBuffer in JS

I am trying to write a file uploader for Meteor framework.我正在尝试为 Meteor 框架编写一个文件上传器。 The principle is to split the fileon the client from an ArrayBuffer in small packets of 4096 bits that are sent to the server through a Meteor.method.原理是将客户端上的文件从 ArrayBuffer 拆分成 4096 位的小数据包,通过 Meteor.method 发送到服务器。

The simplified code below is the part of the client that sends a chunk to the server, it is repeated until offset reaches data.byteLength :下面的简化代码是客户端向服务器发送块的部分,它会重复,直到偏移量达到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

The simplified code below is the part on the server that receives the chunk and writes it to the file system :下面的简化代码是服务器上接收块并将其写入文件系统的部分:

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();
  }
});

I failed to write a valid file to the disk, actually the file is saved but I cannot open it, when I see the content in a text editor, it is similar to the original file (a jpg for example) but some characters are different, I think that could be an encoding problem as the file size is not the same, but I don't know how to fix that...我没有写入有效文件到磁盘,实际上文件已保存但我无法打开它,当我在文本编辑器中看到内容时,它与原始文件(例如jpg)相似,但有些字符不同,我认为这可能是编码问题,因为文件大小不一样,但我不知道如何解决...

Saving the file was as easy as creating a new Buffer with the Uint8Array object :保存文件就像使用 Uint8Array 对象创建一个新的 Buffer 一样简单:

// chunk is the Uint8Array object
fs.appendFile(path, Buffer.from(chunk), function (err) {
    if (err) {
      fut.throw(err);
    } else {
      fut.return(chunk.length);
    }
});

基于Karl.S answer ,这对我有用,在任何框架之外:

fs.appendFileSync(outfile, new Buffer(arrayBuffer));

Just wanted to add that in newer Meteor you could avoid some callback hell with async/await .只是想在较新的 Meteor 中添加它,您可以通过async/await避免一些回调地狱。 Await will also throw and push the error up to client Await 也会抛出错误并将错误推送给客户端

Meteor.methods({
  uploadFileData: async function(file_id, chunk) {
    var path = 'somepath/' + file_id; // be careful with this, make sure to sanitize file_id
    await fs.appendFile(path, new Buffer(chunk));
    return chunk.length;
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM