Nginx+Django环境下MP3文件下载失败问题求助
问题分析与解决方案
首先看你的Nginx错误日志,很明显路径拼接出了大问题:Nginx尝试打开的路径是/var/www/html/project_folder/converter/media/myfile.mp3/downloader/VYOjWnS4cMY/myfile.mp3——这说明你的Nginx配置把请求URL的/downloader/VYOjWnS4cMY/myfile.mp3直接拼到了错误的root路径后面,完全偏离了实际文件的位置。
1. 修正Django视图的X-Accel-Redirect配置
在生产环境下,你用X-Accel-Redirect让Nginx直接提供文件,但当前的路径设置逻辑有误。你需要指定一个Nginx内部可识别的专用路径,而不是直接复用MEDIA_URL(因为MEDIA_URL可能和前端公开访问路径混淆)。
修改视图里的生产环境代码块:
else: # Have Nginx serve the file in production. if not file_exists: return HttpResponseRedirect(reverse('home')) # 先确保文件存在,避免无效请求 response = HttpResponse(content_type='application/force-download') response['Content-Length'] = os.path.getsize(filepath) # 改用内部专用路径,避免和前端访问路由冲突 response['X-Accel-Redirect'] = f'/protected-media/{smart_str(filename)}' # 注意:这里不要带/downloader/VYOjWnS4cMY/部分,那是Django的路由,和Nginx文件路径无关 return response
2. 修正Nginx配置,适配内部重定向
你的现有Nginx配置完全搞错了逻辑——它试图直接匹配前端的下载请求URL,但实际上应该专门处理Django返回的X-Accel-Redirect内部路径。
替换掉你当前的location ~ ^.*/(?P<request_basename>[^/]+\.(mp3))$块,添加以下配置:
# 处理Django的X-Accel-Redirect内部请求,只允许Nginx内部调用,禁止外部直接访问 location /protected-media/ { internal; # alias指向你的实际media目录,注意末尾斜杠要正确 alias /var/www/html/project_name/app_name/media/; } # 保留原有的静态文件配置 location /static/ { root /var/www/html/project_name/app_name; }
为什么这样改?
internal指令确保这个路径只能由Nginx内部调用(比如通过X-Accel-Redirect),不能直接通过浏览器访问,提升安全性。alias会把/protected-media/myfile.mp3精准映射到实际的/var/www/html/project_name/app_name/media/myfile.mp3,完美匹配你的文件存储路径。- Django视图只负责验证权限、确认文件存在,然后把文件路径交给Nginx处理,这才是
X-Accel-Redirect的正确用法。
最后一步
修改完配置后,重启Nginx使更改生效:
sudo systemctl restart nginx
这样再测试下载请求,应该就能正常获取文件了。
内容的提问来源于stack exchange,提问作者Little Phild
相关产品推荐
相关产品推荐

