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
相关产品推荐
相关产品推荐

