如何在同一个Flask接口中同时返回带自定义响应头的JSON信息与文件响应?
如何在同一个Flask接口中同时返回带自定义响应头的JSON信息与文件响应?
兄弟,你的问题我太懂了——Flask的视图函数本来就只能返回一个响应对象,你现在试图同时返回send_file的文件响应和jsonify的JSON响应,这肯定行不通,因为HTTP协议里一个请求对应一个响应,响应体只能有一份内容。不过我们有两种靠谱的解决办法,看你需求选:
方案一:把JSON信息放到自定义响应头里(推荐)
这是最常用的方式,因为文件响应的体已经被文件内容占了,没法同时塞JSON,所以把额外信息转成字符串放到自定义HTTP头里,前端拿到响应后读取这个头就能拿到你要的JSON数据,同时浏览器会自动处理文件下载。
修改你的代码如下:
from flask import Flask, send_file import json app = Flask(__name__) @app.route('/download-pdf', methods=['GET']) def download_pdf(): file_path = 'Frame_relate.pdf' # 生成文件响应 response = send_file(file_path, as_attachment=True, download_name="Frame_relate.pdf") # 设置自定义响应头:把JSON转成字符串放入头部 additional_info = {"message": "File is being downloaded", "status": "success"} response.headers['X-Additional-Info'] = json.dumps(additional_info) # 其实Flask会自动根据响应情况设置状态码,你手动设的Status头可以去掉,或者用标准方式返回状态码 # 如果一定要自定义状态相关的头,建议用标准的状态码字段,比如直接返回 (response, 200) return response if __name__ == '__main__': app.run(debug=True)
解释一下:
- 用
json.dumps()把字典转成JSON字符串,放到自定义的X-Additional-Info头里(自定义头一般用X-前缀区分标准头) - 前端拿到响应后,读取
response.headers.get('X-Additional-Info'),再解析成JSON就能拿到额外信息 - 浏览器会正常触发文件下载,完全不影响
方案二:返回多部分(multipart)响应(不推荐,前端处理麻烦)
如果你的业务一定要把JSON和文件都放在响应体里,那得用multipart/form-data格式的响应,把JSON和文件作为两个不同的部分返回。这种方式需要手动构造多部分响应,前端也得专门解析,非常麻烦,一般只有特殊场景才用。
举个简单的例子(用Werkzeug的MultiPartResponse):
from flask import Flask from werkzeug.wrappers import Response from werkzeug.datastructures import MultiPartResponse, FileStorage import json app = Flask(__name__) @app.route('/download-pdf', methods=['GET']) def download_pdf(): # 准备JSON部分 json_data = json.dumps({"message": "File is being downloaded", "status": "success"}).encode('utf-8') json_part = Response(json_data, mimetype='application/json') # 准备文件部分 file_path = 'Frame_relate.pdf' file_part = FileStorage(open(file_path, 'rb'), filename="Frame_relate.pdf") # 构造多部分响应 multipart_response = MultiPartResponse([ ('json', json_part), ('file', file_part) ]) return multipart_response if __name__ == '__main__': app.run(debug=True)
注意:这种方式前端不能直接触发浏览器下载,必须手动解析多部分内容,提取文件部分再创建下载链接,非常繁琐,所以优先选方案一。
备注:内容来源于stack exchange,提问作者RohithCodez
相关产品推荐
相关产品推荐

