Flask中如何基于流实现send_file与模板渲染共存?
解决方案:Flask中基于流实现文件下载同时加载页面
因为HTTP协议规定单次请求只能返回一个响应,所以无法在同一个return里同时返回文件流和页面模板。要实现加载页面的同时触发流文件下载,可以通过拆分请求的方式实现,以下是具体方案:
核心思路
将文件处理、页面渲染、文件下载拆分为两次请求:
- 第一次POST请求:处理上传的文件,生成处理后的文档流并临时缓存,返回页面模板。
- 第二次GET请求:页面加载完成后,通过前端JS自动发起下载请求,从缓存中取出文档流返回给用户。
代码实现
Flask后端代码
import io import uuid from flask import Flask, request, render_template, send_file, session import aw app = Flask(__name__) app.secret_key = 'your_secure_secret_key' # 临时缓存文档流,生产环境建议用Redis替代内存字典,同时添加过期清理机制 document_cache = {} @app.route('/', methods=['GET','POST']) def homes(): if request.method == 'POST': # 读取上传的文件 document = request.files['test'] stream = io.BytesIO(document.read()) doc = aw.Document(stream) # 执行文档操作(替换为你的业务逻辑) # doc.do_something() # 将处理后的文档写入BytesIO output_stream = io.BytesIO() doc.save(output_stream) output_stream.seek(0) # 将指针移到流开头 # 生成唯一标识,用于后续下载请求 doc_id = str(uuid.uuid4()) document_cache[doc_id] = output_stream session['doc_id'] = doc_id # 返回页面,标记需要触发下载 return render_template("index.html", trigger_download=True) # GET请求直接返回页面 return render_template("index.html", trigger_download=False) @app.route('/download-document') def download_document(): doc_id = session.get('doc_id') if not doc_id or doc_id not in document_cache: return "文档不存在或已过期", 404 # 取出缓存的流并删除,避免内存占用 output_stream = document_cache.pop(doc_id) return send_file( output_stream, as_attachment=True, download_name='test.docx', mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document' )
前端模板(index.html)
在页面中添加JS逻辑,当需要下载时自动触发下载请求:
<!DOCTYPE html> <html> <head> <title>文档处理工具</title> </head> <body> <form method="POST" enctype="multipart/form-data"> <input type="file" name="test" accept=".docx" required> <button type="submit">上传并处理</button> </form> {% if trigger_download %} <script> // 页面加载后自动触发下载,不刷新当前页面 window.onload = function() { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = "{{ url_for('download_document') }}"; document.body.appendChild(iframe); }; </script> {% endif %} </body> </html>
注意事项
- 缓存机制:示例中用内存字典缓存文档流,仅适合开发或低并发场景。生产环境建议使用Redis等分布式缓存,并设置过期时间,避免内存泄漏。
- 大文件处理:如果处理的文档较大,不建议用内存缓存,可临时写入服务器磁盘(处理完成后删除),或直接在前端触发下载时实时生成流(但会增加服务器压力)。
- session安全:确保设置了安全的
secret_key,避免session被篡改。
内容的提问来源于stack exchange,提问作者Finntech
相关产品推荐
相关产品推荐

