Как написать файл из ArrayBuffer в JS
Я пытаюсь написать загрузчик файлов для Meteor framework. Принцип состоит в том, чтобы разделить fileon клиент от ArrayBuffer в небольших пакетах 4096 бит, которые отправляются на сервер через Метеор.метод.
на упрощенный код ниже является частью клиента, который отправляет кусок на сервер, он повторяется до смещение достигает данные.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), но некоторые символы разные, я думаю, что это может быть проблема кодирования, поскольку размер файла не тот же, но я не знаю, как это исправить...
3 ответов
сохранение файла было так же просто, как создание нового буфера с объектом Uint8Array:
// chunk is the Uint8Array object
fs.appendFile(path, new Buffer(chunk), function (err) {
if (err) {
fut.throw(err);
} else {
fut.return(chunk.length);
}
});
дом на Карла.S ответ, это сработало для меня, вне любых рамок:
fs.appendFileSync(outfile, new Buffer(arrayBuffer));
просто хотел добавить, что в более новом Метеоре вы можете избежать какого-то обратного вызова с 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;
}
});