在特殊情况下,我的节点 js 后端收到来自 python Flask 服务器的响应。
我需要将此响应转发回客户端(作为对客户端执行的操作的响应)。
响应应该在客户端浏览器上开始下载 python flask 响应正文中指定的文件。
python烧瓶响应返回的行:
return flask.send_file(download_path, as_attachment=True, attachment_filename=file)
我在我的节点服务器回调中收到此响应:
app.get(constants.routes.files.download, function (req, res) {
fileController.downloadFile(req, (err, response_from_python) => {
console.log("Response from python flask has arrived")
res._headers = response_from_python.headers;
res.set('Content-Disposition', 'attachment; filename=exmp_word.docx');
return res.json(response_from_python.body)
});
这确实会在客户端浏览器上触发下载,但文件已损坏且无法用 word 打开(它是用 word 创建的...)。我认为这与文件在响应正文中的编码方式有关(我应该使用res.json
吗?)。
另外,如果我从客户端直接连接到 python-server(不通过节点),那么文件会成功下载(没有损坏),但这不是它应该工作的方式(应该通过中间的节点服务器) .
我该怎么做?
有没有办法将 python 响应对象直接传递给客户端,而无需将其正文字段复制到节点 res 对象并修改标头?
编辑:
感谢 Ivan Velichko 我没有工作。
这是执行此操作的修改后的函数(我必须更好地构建它,但功能存在)。
app.get(constants.routes.files.download, function (req, res) {
res.set('content-Disposition', 'attachment; filename=noam_susp.docx');
res.set('content-type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
res.set('Accept-Ranges', 'bytes');
res.set('Cache-Control', 'public, max-age=0');
res.set('ETag', 'W/"2721-161b23de2ee');
var file_hash = req.params.identifier;
var request = http.get(constants.manager_rest_api.base_url +
constants.manager_rest_api.get_file_endpoint +
'/' + file_hash + '/download_inner', function(response) {
response.pipe(res);
});
看起来您的解决方案向 python 服务器发出请求,然后读取内存中的整个文件内容,然后仅出于某些原因尝试将其发送回客户端res.json()
。但是,很可能您只需要将客户端的请求转发到 python 服务器,然后按原样转发 python 的响应。你肯定不应该在你的节点服务器上下载文件。而是使用流。就像是:
app.get(constants.routes.files.download, function (req, res) {
fileController.downloadFile(req).pipe(res);
});
要实现此行为,您fileController.downloadFile()
应该返回一个可读流,然后您可以pipe()
将其返回到res
. 而res
本身已经是一个可写的流。
UPD:在管道中明确地将头从 python 的响应复制到节点的响应是很重要的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句