伙计们,当我尝试从FTP获取文件然后通过我的API以base64的形式发送文件时,遇到了Express上的Node.js api问题。
我正在使用-> promise-ftp(https://www.npmjs.com/package/promise-ftp)。
这是端点的样子:
getData = (req, res, next) => {
const ftp = new PromiseFtp();
let data = [];
ftp.connect({host: 'xxxl',user: 'xxx',password: 'xxx'})
.then(() => {
return ftp.get('xxx.pdf');
}).then((stream) => {
return new Promise((resolve, reject) => {
stream.once('close', resolve);
stream.once('error', reject);
stream.pipe(fs.createReadStream('test.pdf'));
stream
.on('error', (err) => {
return res.send({errorMessage: err});
})
.on('data', (chunk) => data.push(chunk))
.on('end', () => {
const buffer = Buffer.concat(data);
label = buffer.toString('base64');
return res.send(label);
});
});
}).then(() => {
return ftp.end();
});
}
问题是我不想将此文件本地保存在api文件旁边,并且当我删除行stream.pipe(fs.createReadStream('test.pdf'));
时不起作用。
我不确定这里是什么管道。
你能帮我吗?
答案 0 :(得分:1)
readable.pipe(writable)
是Node的Stream API的一部分,该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();
}
}
如果您没有支持async
/ await
的Node版本,那么这是一个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());
}
在这里您有一个使用Promise的finally()
方法或try/catch/finally
块的好用例,这将确保即使发生错误也不会调用ftp.end()
。
请注意,我故意将错误发送回客户端,因为这样做可能会泄漏敏感信息。更好的解决方案是使用请求上下文设置适当的服务器端日志记录。