我正在尝试为Meteor框架编写一个文件上传器。 原理是将客户端的文件从ArrayBuffer拆分为4096位的小包,通过Meteor.method发送到服务器。
下面的简化代码是客户端向服务器发送一个块的部分,它会一直重复,直到偏移达到 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
下面的简化代码是服务器上接收块并将其写入文件系统的部分:
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();
}
});
我无法将有效文件写入磁盘,实际上文件已保存但我无法打开它,当我在文本编辑器中看到内容时,它与原始文件(例如jpg)类似,但有些字符是不同的,我认为这可能是一个编码问题,因为文件大小不一样,但我不知道如何修复...
答案 0 :(得分: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);
}
});
答案 1 :(得分:7)
在Karl.S answer的基础上,除了任何框架之外,这对我有用:
fs.appendFileSync(outfile, new Buffer(arrayBuffer));
答案 2 :(得分:1)
只是想在较新的Meteor中添加它,你可以避免使用async/await
的一些回调地狱。 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;
}
});