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

React从Django服务器获取媒体文件的CORS错误求助

React从Django服务器获取图片的问题排查建议

我正尝试通过React应用从Django服务器获取图片,已尝试多种配置方案但均未解决问题,希望能得到相关排查思路或建议。

React端配置

React部署在客户端Nginx之后,请求源始终为http://127.0.0.1而非http://localhost:3000,代码如下:

import axios from "axios"
export async function getImageFromNginx() {
        // 注意:替换{SERVER_URL}为实际服务器地址
        const IMAGE_URL = "http://{SERVER_URL}/media/pages/64d3d8cb4d3bd545823595e4.png"
        const config = {
                mode: 'cors', // 可选值:no-cors, *cors, same-origin
                headers: {
                  'Access-Control-Allow-Origin' : 'http://127.0.0.1',
                  'Access-Control-Allow-Credentials': 'true',
                },
                auth: {'username': 'username', 'password':'password'},
                withCredentials: true,
        }
        console.log(config)
        try{
                const response = await axios.get(IMAGE_URL, config).then((res)=>console.log("axios返回结果",res))
                console.log('已调用Nginx')
                // 注意:图片是二进制数据,调用response.json()会报错,应使用response.data
                return await response.json();
        }catch(error) {
                console.error('获取图片失败', error)
                return [];
        }
}

React端问题点提示

  • 错误的响应处理:图片属于二进制资源,调用response.json()会触发解析错误,需根据需求使用response.data(默认返回Blob类型),或在axios配置中添加responseType: 'blob'/'arraybuffer'。
  • 冗余请求头:Access-Control-Allow-Origin是服务器返回的响应头,客户端无需在请求中设置,应删除该字段。

Django端配置

已安装django-cors-headers并配置应用与中间件,CORS相关设置如下:

# settings.py中的CORS配置
CORS_ALLOWED_ORIGINS = ['http://127.0.0.1']
CORS_ALLOW_CREDENTIALS = True    
CORS_ALLOW_HEADERS = ['Content-Type', 'Access-Control-Allow-Origin']    
CORS_ALLOW_METHODS = ['GET', 'POST', 'OPTIONS']

用于通过Nginx提供文件的Django视图方法:

def send_file(roots, file_name, disposition_type=None, default_file_name=None):
    # 验证文件是否存在于指定根目录
    valid = ['/download/{}'.format(root) for root in roots 
            if os.path.exists(get_absolute_filename(root,file_name))]
    
    if valid:
           response = HttpResponse()
           # Content-Type留空可让Nginx自动识别文件类型,也可手动设置如'image/png'
           response['Content-Type'] = ''
           
           if disposition_type is not None:
                 end_user_filename = default_file_name or file_name
                 response['Content-Disposition'] = "{}; filename={}".format(
                              disposition_type, end_user_filename)
           
           # 让Nginx处理文件发送的X-Accel-Redirect头
           response['X-Accel-Redirect'] = os.path.join(valid[0], file_name)
           
           # 设置CORS响应头
           response['Access-Control-Allow-Origin'] = 'http://127.0.0.1/'
           response['Access-Control-Allow-Methods'] = 'GET'
           response['Access-Control-Allow-Headers'] = 'Content-Type, Access-Control-Allow-Origin'
           response['Access-Control-Allow-Credentials'] = 'true'
    else:
          response = HttpResponseNotFound("请求的文件不存在")
    
    return response

Django端问题点提示

  • CORS配置冗余:Access-Control-Allow-Origin是响应头,无需加入CORS_ALLOW_HEADERS(该配置用于允许客户端发送的请求头),应移除。
  • 路径一致性检查:确保X-Accel-Redirect中的/download/路径与Nginx配置中的location /download/对应,且文件实际存在于Nginx指定的目录下。

服务器端Nginx配置

CORS相关代码片段:

# 处理文件下载的location
location /download/ {
        alias /media/;
        internal; # 仅允许内部请求访问
        # 始终添加CORS响应头(包含错误响应)
        add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1/' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Access-Control-Allow-Origin' always;
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
        add_header 'Access-Control-Allow-Credentials' 'true';
}

# 处理其他请求的location
location / {
        # 处理OPTIONS预请求
        if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1/';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                # 允许客户端发送的请求头
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Access-Control-Allow-Origin';
                # 预请求缓存有效期20天
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain; charset=utf-8';
                add_header 'Content-Length' 0;
                add_header 'Access-Control-Allow-Credentials' 'true';
                return 204;
        }

        # 处理POST请求
        if ($request_method = 'POST') {
                add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1/' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Access-Control-Allow-Origin' always;
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
                add_header 'Access-Control-Allow-Credentials' 'true';
        }

        # 处理GET请求
        if ($request_method = 'GET') {
                add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1/' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Access-Control-Allow-Origin' always;
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
                add_header 'Access-Control-Allow-Credentials' 'true';
        }
}

Nginx端问题点提示

  • 源路径一致性:http://127.0.0.1和http://127.0.0.1/(带斜杠)属于不同源,需确保客户端请求的Origin与服务器配置完全一致。
  • internal限制验证:location /download/设置了internal,仅允许通过Django的X-Accel-Redirect访问,直接访问该路径会返回404,此为正常逻辑,但需确保Django生成的重定向路径正确。

通用排查步骤

  • 打开浏览器开发者工具(F12),查看Network标签下的请求详情,确认是CORS错误、404错误还是权限问题。
  • 验证图片文件是否存在于Nginx的/media/目录下,且路径与请求的/media/pages/xxx.png完全匹配(需同步检查Django的MEDIA_URL和MEDIA_ROOT配置)。
  • 在浏览器中直接访问图片URL,确认文件本身可正常访问,排除文件损坏或路径错误问题。
  • 临时简化配置测试:比如设置CORS_ALLOW_ALL_ORIGINS = True(仅用于测试),关闭credentials验证,缩小问题范围。
  • 查看Nginx的访问日志和错误日志,确认请求是否到达Nginx,以及是否存在路径匹配错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:35:53