我真的在为 connect-busboy 和流式写作而苦苦挣扎。问题是我想做一些文件验证,但如果不先处理数据就无法做到这一点,而且似乎我必须在处理它时将其写入文件。
当数据进入并且我遇到文件大小或文件类型限制等错误时,我拒绝了请求,但文件的一部分已经写入磁盘。我真的很想省略写入直到最后,或者可能将其暂存到内存缓冲区中。
此代码将拒绝无效的文件类型和大小限制,但它始终首先创建写入流并将文件通过管道传输到其中。我真正想做的是移动“file.pipe(fstream);” 进入 file.on('end',... 回调,但这当然不起作用,因为它必须在它进入时写入。所以看起来我需要先将它写入暂存缓冲区,然后在结束将它刷新到一个真实文件。或者我可以写入一个临时文件,并在出错时删除该文件,但这似乎更加hacky和脆弱。对于这个看似常见的问题,最佳实践是什么?
saveFiles: function(request, options) {
return new Promise(function(resolve, reject) {
var fstream;
var totalData = 0;
request.pipe(request.busboy);
var fileIds = [];
var assets = {'assets': {}};
request.busboy.on('file', function(fieldname, file, originalName, encoding, contype) {
file.on('limit', function() {
var limitBytes = request.busboy.opts.limits.fileSize;
var limitMB = Math.round((limitBytes / 1048576) * 100) / 100;
return reject({errorMsg: 'Files exceeded the size limit of ' + limitMB + 'MB'});
});
file.on('data', function(data) {
if (totalData === 0) {
var type = fileType(data);
if(type) {
if (request.busboy.opts.limits.validFileTypes.indexOf(type.ext) === -1) {
return reject({errorMsg: 'Invalid file type "' + type.ext + '"'});
}
}
else {
return reject({errorMsg: 'Invalid file type'});
}
}
totalData += data.length;
});
var fileId = uuid.v1(); // used for file name on server
var parts = originalName.split('.');
var extension = parts[parts.length - 1].toLowerCase();
var fileName = fileId + '.' + extension;
fstream = fs.createWriteStream(__assets + fileName);
file.pipe(fstream);
file.on('end', function() {
assets['assets'][fileId] = {
fileName: fileId + '.' + extension,
originalName: originalName
};
});
});
request.busboy.on('finish', function(){
resolve(assets);
});
});
}