You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fetch无法接收Flask send_file()返回的响应头问题求助

问题解决:Flask后端传递Content-Disposition头,Vue前端Fetch无法获取的方案

核心原因

跨域请求场景下,浏览器默认仅允许前端获取简单响应头(如Content-Type、Cache-Control等),像Content-Disposition这类自定义/非标准头,必须由后端通过Access-Control-Expose-Headers明确指定暴露给前端,否则浏览器会隐藏这些头,导致前端无法读取。


解决方案

1. 使用Flask-CORS扩展(推荐)

这是最简便的跨域配置方式,能全局或针对路由指定要暴露的响应头:

  • 先安装依赖:
    pip install flask-cors
    
  • 全局配置(所有路由生效):
    from flask import Flask
    from flask_cors import CORS
    
    app = Flask(__name__)
    # 配置CORS,暴露Content-Disposition头
    CORS(app, expose_headers=["Content-Disposition"])
    
  • 单路由配置(仅目标接口生效):
    from flask_cors import cross_origin
    
    @app.route('/rdownload/<id>')
    @cross_origin(expose_headers=["Content-Disposition"])
    def rdownload(id):
        # 你的文件返回逻辑,推荐用第一种send_file参数方式
        return send_file(base_path + filename, as_attachment=True, download_name=filename)
    

2. 手动添加响应头(无需扩展)

如果不想引入Flask-CORS,可在每个需要的响应中手动添加暴露头:

from flask import make_response, send_file

@app.route('/rdownload/<id>')
def rdownload(id):
    response = make_response(send_file(base_path + filename, as_attachment=True, download_name=filename))
    # 明确暴露Content-Disposition给前端
    response.headers['Access-Control-Expose-Headers'] = 'Content-Disposition'
    return response

3. 前端适配(获取并解析文件名)

配置后端后,前端即可正常读取响应头,示例代码:

fetch('http://localhost:4999/rdownload/' + this.$route.params.id, {
  method: 'GET'
}).then(res => {
  if (res.status === 500) {
    // 错误处理逻辑
    return;
  }
  // 读取Content-Disposition头
  const dispositionHeader = res.headers.get('Content-Disposition');
  // 解析文件名(兼容带引号和不带引号的格式)
  const filenameMatch = dispositionHeader.match(/filename="?([^"]+)"?/);
  const filename = filenameMatch ? filenameMatch[1] : 'unknown-file';

  res.blob().then((blob) => {
    // 用解析出的文件名触发下载
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
    document.body.removeChild(a);
  })
})

额外优化:处理中文文件名乱码

如果文件名包含中文,建议后端对文件名进行URL编码,避免乱码:

from urllib.parse import quote

@app.route('/rdownload/<id>')
@cross_origin(expose_headers=["Content-Disposition"])
def rdownload(id):
    encoded_filename = quote(filename)
    # 同时设置兼容旧浏览器的filename和标准的filename*字段
    return send_file(
        base_path + filename,
        as_attachment=True,
        download_name=filename,
        headers={
            'Content-Disposition': f'attachment; filename="{filename}"; filename*=UTF-8''{encoded_filename}'
        }
    )

内容的提问来源于stack exchange,提问作者Insomnes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 21:51:16