在特殊情况下,我的节点js后端收到来自python flask服务器的响应。
我需要将此响应转发回客户端(作为对客户端执行的操作的响应)。
响应应该在客户端浏览器上开始下载python flask响应体中指定的文件。
来自python flask的响应返回行:
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响应对象直接传递给客户端而不将其body字段复制到node 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);
});
答案 0 :(得分:1)
看起来您的解决方案向python服务器发出请求,然后读取内存中的整个文件内容,然后尝试使用某些原因将其发送回客户端res.json()
。但是,很可能你只需要将客户端的请求转发给python服务器,然后按原样转发python的响应。而且您肯定不应该在节点服务器上下载文件。而是使用streams。类似的东西:
app.get(constants.routes.files.download, function (req, res) {
fileController.downloadFile(req).pipe(res);
});
要实现此行为,您的fileController.downloadFile()
应该返回一个可读的流,然后您可以pipe()
到res
。并且res
本身已经是可写流。
UPD:在管道输入之前,明确地将python响应中的标头复制到节点的响应中非常重要。