Django本地文件下载路径问题求助
Django本地文件下载功能修复方案
1. HTML模板URL标签错误修正
你当前的a标签{% url 'download/path' %}写法不符合Django路由规则,正确的写法需要传入路由名称和对应的路径参数:
<div class="com"> {{plik.localisation}} <a href="{% url 'download' path=plik.localisation %}" class="button">download</a> </div>
这里download是你在urls.py中定义的路由name,path=plik.localisation用于将文件路径参数传递给视图函数。
2. 视图函数优化与下载行为调整
- 你当前使用
Content-Disposition: inline是让浏览器在线打开PDF,若要触发本地下载,需改为attachment; - 推荐使用Django原生的
FileResponse替代HttpResponse,它更适合处理文件流,性能更优:
from django.http import FileResponse, Http404 import os from django.conf import settings def download(request, path): file_path = os.path.join(settings.MEDIA_ROOT, path) if os.path.exists(file_path) and os.path.isfile(file_path): return FileResponse(open(file_path, 'rb'), as_attachment=True, filename=os.path.basename(file_path)) raise Http404
3. 路径合法性校验
确保plik.localisation存储的是相对于MEDIA_ROOT的相对路径,而非绝对路径或包含../的层级跳转路径(后者存在安全风险)。比如MEDIA_ROOT为/home/user/media/,那么plik.localisation应是docs/report.pdf这类格式。
4. 安全加固(防止路径遍历攻击)
为避免恶意用户通过构造路径访问MEDIA_ROOT外的文件,可在视图中增加路径校验逻辑:
from django.http import FileResponse, Http404 import os from django.conf import settings def download(request, path): # 规范化路径,去除相对层级跳转 normalized_path = os.path.normpath(path) if normalized_path.startswith('..'): raise Http404 file_path = os.path.join(settings.MEDIA_ROOT, normalized_path) # 二次校验确保文件在MEDIA_ROOT范围内 if not file_path.startswith(settings.MEDIA_ROOT): raise Http404 if os.path.exists(file_path) and os.path.isfile(file_path): return FileResponse(open(file_path, 'rb'), as_attachment=True, filename=os.path.basename(file_path)) raise Http404
内容的提问来源于stack exchange,提问作者Robert Wyszynski
相关产品推荐
相关产品推荐

