Node.js - 在管道响应之前检查流是否有错误
Node.js - Check if stream has error before piping response
在 Node.js 中,假设我想从某处读取文件并流式传输响应(例如,使用 fs.createReadStream()
从文件系统)。
application.get('/files/:id', function (request, response) {
var readStream = fs.createReadStream('/saved-files/' + request.params.id);
var mimeType = getMimeTypeSomehow(request.params.id);
if (mimeType === 'application/pdf') {
response.set('Content-Range', ...);
response.status(206);
} else {
response.status(200);
}
readStream.pipe(response);
});
但是,我想在发送响应之前检测流是否有错误 headers。我该怎么做?
伪代码:
application.get('/files/:id', function (request, response) {
var readStream = fs.createReadStream('/saved-files/' + request.params.id);
readStream.on('ready', function () {
var mimeType = getMimeTypeSomehow(request.params.id);
if (mimeType === 'application/pdf') {
response.set('Content-Range', ...);
response.status(206);
} else {
response.status(200);
}
readStream.pipe(response);
});
readStream.on('error', function () {
response.status(404).end();
});
});
写流在readStream结束或出错时结束。您可以通过在管道期间传递 end:false
并手动结束写入流来防止此默认行为。
因此,即使发生错误,您的写入流仍然打开,您可以在 error
回调中使用 writestream 执行其他操作(例如发送 404 状态)。
var readStream = fs.createReadStream('/saved-files/' + request.params.id);
readStream.on('error', function () {
res.status(404).end();
});
readStream.on('end', function(){
res.end(); //end write stream manually when readstream ends
})
readStream.pipe(res,{end:false}); // prevent default behaviour
更新1:对于文件流,可以监听open
事件来检查文件是否准备好读取:
readStream.on('open', function () {
// set response headers and status
});
更新 2:正如 OP 提到的,其他流可能没有 open
事件,如果流是从节点的流模块继承的,我们可以使用以下内容。诀窍是我们手动写入数据而不是 pipe()
方法。这样我们就可以在开始写入第一个字节之前对 writable 做一些 'initialization' 。
所以我们先绑定once('data')
,再绑定on('data')
。第一个将在实际写入发生之前被调用。
readStream
.on('error',function(err) {
res.status(404).end();
})
.once('data',function(){
//will be called once and before the on('data') callback
//so it's safe to set headers here
res.set('Content-Type', 'text/html');
})
.on('data', function(chunk){
//now start writing data
res.write(chunk);
})
.on('end',res.end.bind(res)); //ending writable when readable ends
在 Node.js 中,假设我想从某处读取文件并流式传输响应(例如,使用 fs.createReadStream()
从文件系统)。
application.get('/files/:id', function (request, response) {
var readStream = fs.createReadStream('/saved-files/' + request.params.id);
var mimeType = getMimeTypeSomehow(request.params.id);
if (mimeType === 'application/pdf') {
response.set('Content-Range', ...);
response.status(206);
} else {
response.status(200);
}
readStream.pipe(response);
});
但是,我想在发送响应之前检测流是否有错误 headers。我该怎么做?
伪代码:
application.get('/files/:id', function (request, response) {
var readStream = fs.createReadStream('/saved-files/' + request.params.id);
readStream.on('ready', function () {
var mimeType = getMimeTypeSomehow(request.params.id);
if (mimeType === 'application/pdf') {
response.set('Content-Range', ...);
response.status(206);
} else {
response.status(200);
}
readStream.pipe(response);
});
readStream.on('error', function () {
response.status(404).end();
});
});
写流在readStream结束或出错时结束。您可以通过在管道期间传递 end:false
并手动结束写入流来防止此默认行为。
因此,即使发生错误,您的写入流仍然打开,您可以在 error
回调中使用 writestream 执行其他操作(例如发送 404 状态)。
var readStream = fs.createReadStream('/saved-files/' + request.params.id);
readStream.on('error', function () {
res.status(404).end();
});
readStream.on('end', function(){
res.end(); //end write stream manually when readstream ends
})
readStream.pipe(res,{end:false}); // prevent default behaviour
更新1:对于文件流,可以监听open
事件来检查文件是否准备好读取:
readStream.on('open', function () {
// set response headers and status
});
更新 2:正如 OP 提到的,其他流可能没有 open
事件,如果流是从节点的流模块继承的,我们可以使用以下内容。诀窍是我们手动写入数据而不是 pipe()
方法。这样我们就可以在开始写入第一个字节之前对 writable 做一些 'initialization' 。
所以我们先绑定once('data')
,再绑定on('data')
。第一个将在实际写入发生之前被调用。
readStream
.on('error',function(err) {
res.status(404).end();
})
.once('data',function(){
//will be called once and before the on('data') callback
//so it's safe to set headers here
res.set('Content-Type', 'text/html');
})
.on('data', function(chunk){
//now start writing data
res.write(chunk);
})
.on('end',res.end.bind(res)); //ending writable when readable ends