Flask中如何直接触发第三方API返回的PDF文件下载?
问题分析
Flask 的 send_file() 函数默认将传入的字符串视为本地文件路径,而你传入的是 Api2Pdf 返回的远程 URL,因此它错误地把 URL 拼接到了当前应用的本地目录下,导致路径格式非法,触发了 OSError。
解决方案
以下两种方法可实现无需本地存储,直接让用户下载第三方返回的 PDF 文件:
方案一:直接重定向到 PDF 下载 URL(最简实现)
直接返回重定向响应,让浏览器从 Api2Pdf 的 URL 直接下载文件。若希望浏览器强制下载而非在线预览,可通过响应头控制。
修改 generateReport 视图函数:
from flask import redirect, make_response @app.route('/generatereport', methods=['GET']) @login_required def generateReport(): precords = people.find({"parentrecord": current_user.user_json['_id']}).sort('nextContact', pymongo.ASCENDING) todayDate = date.today() pdf_url = pdfgeneratorv2(info=precords, date=todayDate, user=current_user.user_json) # 生成重定向响应,强制浏览器触发下载 response = make_response(redirect(pdf_url)) response.headers['Content-Disposition'] = 'attachment; filename="Networking Report.pdf"' return response
方案二:代理 PDF 内容(隐藏第三方 URL)
如果不想暴露 Api2Pdf 的原始 URL,可通过 requests 库获取 PDF 字节内容,再通过 send_file 返回(无需保存到本地磁盘)。
步骤:
- 先安装依赖:
pip install requests
- 修改视图函数:
from flask import send_file import requests from io import BytesIO @app.route('/generatereport', methods=['GET']) @login_required def generateReport(): precords = people.find({"parentrecord": current_user.user_json['_id']}).sort('nextContact', pymongo.ASCENDING) todayDate = date.today() pdf_url = pdfgeneratorv2(info=precords, date=todayDate, user=current_user.user_json) # 请求第三方 PDF 资源 res = requests.get(pdf_url) res.raise_for_status() # 捕获请求失败的异常 # 将字节内容存入内存对象 pdf_buffer = BytesIO(res.content) # 返回文件下载响应 return send_file( pdf_buffer, as_attachment=True, download_name='Networking Report.pdf', mimetype='application/pdf' )
注意事项
- 方案一优势:实现简单,无需消耗服务器带宽;劣势:用户可能看到第三方 URL。
- 方案二优势:隐藏第三方 URL,下载流程完全由自己的服务器控制;劣势:会消耗服务器带宽,大文件场景需注意内存占用。
- 确保 Api2Pdf 返回的 URL 是公开可访问的,若 URL 有过期时间或签名验证,需保证请求时 URL 处于有效状态。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

