我正在使用node和express来处理文件上传,并且我使用多方/busboy和request将它们直接流式传输到转换服务。
有没有办法在将流发送到相应的提供程序之前验证流是否具有某些文件类型?我尝试 https://github.com/mscdex/mmmagic 从第一个块中取出 MIME 类型,效果很好。我想知道以下工作流程是否以某种方式工作:
- 缓冲文件上传流并检查 Mime 类型的传入数据。
- 检查前几个块并且 mime 类型正确时,将缓冲区清空到请求流中。
- 当 MIME 类型不正确时,发送错误消息并返回。
我试图让它工作,但我似乎有一些流兼容性问题(节点 0.8.x 与节点 0.10.x 流,请求库不支持这些问题)。
是否有任何最佳实践来解决此问题?我是不是看错了?
编辑:感谢保罗,我想出了这个代码:
https://gist.github.com/chmanie/8520572
除了检查客户端请求的Content-Type
标头之外,我不知道检查MIME类型的更好,更聪明的方法。
可以使用转换流实现上述解决方案。在此示例中,转换流缓冲一些任意数量的数据,然后将其发送到 MIME 检查库。如果一切正常,它会重新发出数据。后续区块将按原样发出。
var stream = require('readable-stream');
var mmm = require('mmmagic');
var mimeChecker = new stream.Transform();
mimeChecker.data = [];
mimeChecker.mimeFound = false;
mimeChecker._transform = function (chunk, encoding, done) {
var self = this;
if (self.mimeFound) {
self.push(chunk);
return done();
}
self.data.push(chunk);
if (self.data.length < 10) {
return done();
}
else if (self.data.length === 10) {
var buffered = Buffer.concat(this.data);
new mmm.Magic(mmm.MAGIC_MIME_TYPE).detect(buffered, function(err, result) {
if (err) return self.emit('error', err);
if (result !== 'text/plain') return self.emit('error', new Error('Wrong MIME'));
self.data.map(self.push.bind(self));
self.mimeFound = true;
return done();
});
}
};
然后,您可以将此转换流通过管道传输到任何其他流,例如请求流(顺便说一下,它完全支持 Node 0.10 流)。
// Usage example
var fs = require('fs');
fs.createReadStream('input.txt').pipe(mimeChecker).pipe(fs.createWriteStream('output.txt'));
编辑:为了更清楚地了解节点 0.8 和 0.10 流之间遇到的不兼容性,当您定义流并向其附加一个.on('data')
侦听器时,它将切换到流模式(又名 0.8 流),这意味着即使目标不侦听,它也会发出数据。如果您发起异步请求以Magic.detect()
,就会发生这种情况:即使您侦听它,数据仍然在流动。