readable.pipe(writable)
является частью потокового API узла, который прозрачно записывает данные, которые считываются из читаемого в поток для записи, обрабатывая обратное давление для вас. Передача данных в файловую систему не требуется, и объект Express Response
реализует интерфейс потока с возможностью записи, поэтому вы можете просто направить поток, возвращенный из обещания FTP, непосредственно в объект res
.
getData = async (req, res) => {
const ftp = new PromiseFtp();
try {
await ftp.connect({host: 'xxxl',user: 'xxx',password: 'xxx'});
const stream = await ftp.get('xxx.pdf');
res.type('pdf');
await new Promise((resolve, reject) => {
res.on('finish', resolve);
stream.once('error', reject);
stream.pipe(res);
});
} catch(e) {
console.error(e);
} finally {
await ftp.end();
}
}
Если у вас нет версии Node, поддерживающей async
/ await
, вот версия для Promise:
getData = (req, res) => {
const ftp = new PromiseFtp();
ftp
.connect({host: 'xxxl',user: 'xxx',password: 'xxx'})
.then(() => ftp.get('xxx.pdf'))
.then(stream => {
res.type('pdf');
return new Promise((resolve, reject) => {
res.on('finish', resolve);
stream.once('error', reject);
stream.pipe(res);
});
})
.catch(e => {
console.error(e);
})
.finally(() => ftp.end());
}
Здесь у вас есть хороший вариант использования метода finally()
Promise или блока try/catch/finally
, который будет гарантировать, что ftp.end()
вызывается, даже если происходит ошибка или нет.
Обратите внимание, что я намеренно исключил отправку ошибки клиентам, поскольку такие действия могут привести к утечке конфиденциальной информации. Лучшее решение - настроить правильное ведение журнала на стороне сервера с контекстом запроса.