Flask下载中断检测:如何在用户取消下载时触发自定义函数?
Flask流式下载中捕获连接中断/取消事件的处理方法
当用户取消下载或连接中断时,Flask默认不会主动触发自定义逻辑,需要通过包装生成器并捕获相关异常来实现。以下是具体实现方案:
自定义带中断回调的生成器
先定义一个包装函数,在迭代响应内容时捕获连接异常,并触发自定义回调:
from flask import Response, stream_with_context import requests def stream_with_callback(response, chunk_size=2048, on_interrupt=None): try: # 迭代流式响应内容 for chunk in response.iter_content(chunk_size=chunk_size): yield chunk except (IOError, BrokenPipeError, ConnectionResetError) as e: # 触发自定义中断处理函数 if on_interrupt: on_interrupt() # 重新抛出异常,让WSGI服务器正确处理连接关闭 raise
在API中使用该生成器
编写你的自定义中断处理函数,替换原有的流式响应逻辑:
def handle_download_interrupt(): # 这里编写你的自定义逻辑,比如: # - 记录用户取消下载的日志 # - 清理临时资源 # - 通知后端服务停止相关任务 print("检测到下载中断:用户取消或连接断开") # 原API逻辑修改 @app.route('/download') def download(): url = "你的数据源URL" ssl_context = "你的SSL配置" headers = {"Content-Type": "application/octet-stream"} r = requests.get(url, stream=True, timeout=180, verify=ssl_context) # 使用自定义生成器包装响应流 return Response( stream_with_context(stream_with_callback(r, on_interrupt=handle_download_interrupt)), headers=headers )
关键说明
- 不同WSGI服务器(如uWSGI、Gunicorn)抛出的连接异常类型可能略有差异,
IOError、BrokenPipeError、ConnectionResetError是最常见的几种,可根据实际日志补充异常类型。 - 捕获异常后重新抛出是为了让服务器正确处理连接关闭流程,避免资源泄漏。
- 如果需要主动关闭requests的连接,可在
handle_download_interrupt中调用r.close(),不过正常迭代结束后requests会自动关闭连接,异常场景下手动关闭更稳妥。
内容的提问来源于stack exchange,提问作者brainoverflow
相关产品推荐
相关产品推荐

