Flask 下载时数据流的返回
关于flask 的下载功能实现,网上有一大堆,大致上是这样(适用于预下载的文件就在你的服务器里)
from flask import jsonify, json, request, make_response, Response, stream_with_context, send_file import mimetypes @api.route("/downloadFile/<path:filename>") def downloadFile(filename): import os baseDir = os.path.join(os.getcwd(), "static") pathname = os.path.join(baseDir, filename) print pathname def send_chunk(): # 流式读取 store_path = pathname with open(store_path, 'rb') as target_file: while True: chunk = target_file.read(20 * 1024 * 1024) # 每次读取20M if not chunk: break yield chunk return Response(send_chunk(), content_type='application/octet-stream') @api.route("/downloadFile2/<path:filename>") def downloadFile2(filename): import os baseDir = os.path.join(os.getcwd(), "static") pathname = os.path.join(baseDir, filename) f = open(pathname, "rb") response = Response(f.readlines()) # response = make_response(f.read()) mime_type = mimetypes.guess_type(filename)[0] response.headers['Content-Type'] = mime_type response.headers['Content-Disposition'] = 'attachment; filename={}'.format(filename.encode().decode('latin-1')) return response
但是我遇到的情况是下载的文件不在本地服务器,所以按上面的逻辑的话,我需要自己先下载好了才能传输给用户,可以说有点蠢
所以经过研究,发现了一种解决办法(跳过自己下载好了再传输的尴尬,直接将请求到的数据返回给用户)
from werkzeug._compat import wsgi_encoding_dance
@app.route("/downloadFile/<hash_str>") def download_file(hash_str): song = get_download_link(hash_str) # 首先定义一个生成器,每次读取512个字节 def generate(): if song['url']: r = requests.get(song['url'], cookies=request.cookies, stream=True) for chunk in r.iter_content(chunk_size=512): if chunk: yield chunk response = Response(stream_with_context(generate())) name = wsgi_encoding_dance(FileName) # .encode("utf-8").decode("latin1") content_disposition = "attachment; filename={}".format(name) response.headers['Content-Disposition'] = content_disposition return response