[英]Redirect a download file from API server in Python
I have 2 server: one backend for API and another one as web-frontend.我有 2 台服务器:一台用于 API 的后端,另一台作为 Web 前端。 The backend is working and provides files:后端正在工作并提供文件:
#API class for the route in Flask
class DownloadDocument(Resource):
def get(self):
# accept the filename which must be downloaded in HTTP request.
# That file is surely present in the directory
filename = request.headers.get('x-filename')
return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
The web-frontend is currently getting the file in this way:网络前端目前正在以这种方式获取文件:
@app.route('/get_doc/<filename>')
@login_required
def get_doc(filename):
sending = {'x-filename': filename}
response = requests.get('http://<<api_server>>', headers=sending)
return response.content
The result is that when I click download in the webpage ( http://<<frontend>>/get_doc/20201116003_895083.jpg
), I see the file as text and not downloaded.结果是,当我在网页( http://<<frontend>>/get_doc/20201116003_895083.jpg
)中单击下载时,我将文件视为文本而不是下载。 For example, I see a big page full of that:例如,我看到一个很大的页面:
����]ExifII*����
I don't understand if the problem is in the frontend or in the backend.我不明白问题是在前端还是在后端。 In the frontend, I tried with urllib.request.Request or requests.request .在前端,我尝试使用urllib.request.Request或requests.request 。 Any idea how to manage this kind of download?知道如何管理这种下载吗? Probably is something related to mime interpretation, bytes download or buffer it locally.可能与 mime 解释、字节下载或本地缓冲有关。 Of course, I don't want to download the file in the web-frontend storage.当然,我不想在网络前端存储中下载文件。 I want to redirect it to the visitor.我想将其重定向给访问者。
Here are the headers from GET:以下是 GET 的标头:
{'Content-Disposition': 'attachment; filename=20201116003_895083.jpg', 'Content-Length': '574424', 'Content-Type': 'image/jpeg', 'Last-Modified': 'Tue, 01 Dec 2020 14:04:30 GMT', 'Cache-Control': 'public, max-age=43200', 'Expires': 'Thu, 03 Dec 2020 02:34:51 GMT', 'ETag': '"1606831470.89299-574424-736697678"', 'Date': 'Wed, 02 Dec 2020 14:34:51 GMT', 'Server': 'Werkzeug/1.0.1 Python/3.8.3'}
I'm not sure if this is a good way to architect your application.我不确定这是否是构建应用程序的好方法。 I think the Restful backend is intended to work with a Javascript frontend, rather than a separate Flask app which contacts the 'backend' with the requests
library.我认为 Restful 后端旨在与 Javascript 前端一起使用,而不是与requests
库联系“后端”的单独 Flask 应用程序一起使用。 I'm not sure how this would behave in a larger app.我不确定这在更大的应用程序中会如何表现。 The requests
documentation raises some prod considerations about timeouts for example.例如, requests
文档提出了一些关于超时的建议。 You may see some unforseen issues down the line when deploying this with a WSGI server.使用 WSGI 服务器部署它时,您可能会看到一些无法预料的问题。 (imo) (海事组织)
However, with that considered, a quick fix for the actual issue would be to use the flask.send_file
function to return the file.但是,考虑到这一点,实际问题的快速解决方法是使用flask.send_file
function 来返回文件。 This accepts a file pointer as the first argument, so you'll need to use io.BytesIO
to convert the bytes object:这接受文件指针作为第一个参数,因此您需要使用io.BytesIO
来转换字节 object:
from flask import send_file
from io import BytesIO
@app.route('/get_doc/<filename>')
@login_required
def get_doc(filename):
sending = {'x-filename': filename}
response = requests.get('http://<<api_server>>', headers=sending)
return send_file(BytesIO(response.content), mimetype='image/jpeg'
#as_attachment=True
)
You also need to provide the mimetype
argument, as usually send_file
guesses the mimetype based on the extension when a string like 'file.jpg'
is passed as the first arg.您还需要提供mimetype
参数,因为当像'file.jpg'
这样的字符串作为第一个参数传递时, send_file
通常会根据扩展名猜测 mimetype。 Obviously that can't be done in this case.显然,在这种情况下不能这样做。
You can also pass as_attachment=True
if you want the user to receive a download prompt, rather that viewing the image in-browser.如果您希望用户收到下载提示,而不是在浏览器中查看图像,您也可以传递as_attachment=True
。 This is all mentioned in thesend_file
docs .这在send_file
文档中都提到了。
Again, this feels like a hack.再一次,这感觉就像一个黑客。 Something seems off with using the requests
library in this way.以这种方式使用requests
库似乎有些不对劲。 Perhaps other SO users will be able to comment further on this.也许其他 SO 用户将能够对此发表进一步评论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.