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

DRF向客户端发送视频文件下载时客户端请求报错问题咨询

这种浏览器直接访问正常但客户端AJAX请求炸锅的情况我太熟了,大概率逃不过下面这几个坑,咱们挨个排查:

排查与解决方案

1. 先盯紧CORS跨域问题

浏览器直接输入URL属于简单请求,不会触发CORS预检,但客户端发起的XMLHttpRequest/fetch请求如果是跨域场景(比如前后端分离部署),就会触发浏览器的CORS校验。

你可以打开浏览器开发者工具的Network面板,查看客户端请求的响应头:

  • 有没有Access-Control-Allow-Origin头,值是否包含你的客户端域名?
  • 有没有Access-Control-Allow-Methods,是否包含GET(毕竟下载是GET请求)?

如果没有这些头,服务器端必须补上。比如用Express的话,直接用cors()中间件;如果是Python Flask,就手动设置响应头:

@app.after_request
def add_cors_headers(response):
    response.headers['Access-Control-Allow-Origin'] = 'http://your-client-domain.com'
    response.headers['Access-Control-Allow-Methods'] = 'GET'
    return response

2. 客户端请求的响应类型必须设对

下载视频是二进制数据,而很多HTTP请求库(比如Angular HttpClient、Axios)默认的响应类型是json,这会导致客户端试图把二进制文件当成JSON解析,直接报错0 Unknown Error。

Angular HttpClient示例:

this.http.get('http://localhost:8000/api/v1/store/download/?q=xxx', { 
  responseType: 'blob' // 必须设为blob
}).subscribe(blob => {
  // 生成下载链接
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'target-video.mp4'; // 自定义文件名
  a.click();
  window.URL.revokeObjectURL(url); // 释放资源
});

Axios示例:

axios.get('http://localhost:8000/api/v1/store/download/?q=xxx', {
  responseType: 'blob'
}).then(res => {
  const url = window.URL.createObjectURL(res.data);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'target-video.mp4';
  a.click();
  window.URL.revokeObjectURL(url);
});

3. URL参数的特殊字符要编码

你的请求参数q里包含逗号(,)和斜杠(/)这些特殊字符,浏览器直接访问会自动编码,但客户端拼接URL时如果没手动编码,可能导致服务器解析参数出错。

一定要用encodeURIComponent()编码参数值:

const qParam = 'e8000074ab4d,eJwLyygpKbDS18/JT07MycgvLrGyMDAw0C8tyMlPTNFPy8xJ1U9M1MstMOEqMODSAwB4gQ8P';
const encodedQ = encodeURIComponent(qParam);
const finalUrl = `http://localhost:8000/api/v1/store/download/?q=${encodedQ}`;

4. 服务器端的响应头要配置正确

服务器返回文件时,必须设置正确的Content-Disposition和Content-Type头,告诉浏览器这是需要下载的文件,而非直接播放的资源。

比如Flask的示例:

from flask import send_file, request

@app.route('/api/v1/store/download/')
def download_file():
    q = request.args.get('q')
    # 根据q获取文件路径
    file_path = get_file_path_by_hash(q)
    return send_file(
        file_path,
        mimetype='video/mp4', # 对应你的视频类型,比如video/avi、video/mov
        as_attachment=True, # 关键:触发下载而非播放
        download_name='your-video.mp4' # 自定义下载文件名
    )

5. 检查客户端的请求拦截器

如果你的项目用了请求拦截器(比如Angular的HttpInterceptor、Axios的interceptors),有可能拦截器修改了请求头或者错误地处理了响应。可以暂时禁用拦截器测试,如果能正常下载,那就是拦截器的逻辑有问题,比如添加了不必要的自定义头,或者在响应阶段提前抛出了错误。


先从CORS配置和responseType设置这两个最常见的坑开始排查,基本能解决大部分问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:23:26