Django模板下载文件返回HTML格式 如何获取原格式文件?
Django下载文件返回HTML格式问题解决方案
问题根源
原有两个实现的核心错误如下:
- 第一个版本
download_link方法没有return语句,模板渲染时拿到空值,点击链接会默认请求当前页面,下载到的就是当前页面的HTML内容 - 第二个版本错误地将HttpResponse响应逻辑写在模型方法中,模板调用时只会将响应对象转为字符串输出,不会触发实际的下载逻辑;同时打开文件使用文本模式
'r',二进制文件(PDF、压缩包等)会直接损坏,文件名固定后缀也不符合实际文件格式。
方案1:直接使用FileField的URL(适合无需权限控制的场景)
1. 配置项目媒体资源参数
在settings.py中添加如下配置:
MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media'
2. 配置开发环境媒体路由
在项目根目录的urls.py中添加媒体资源访问路由:
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 原有其他路由 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
生产环境直接用Nginx/Apache代理
/media/路径即可,无需配置此路由。
3. 模板直接调用
无需在模型中自定义download_link方法,模板直接写:
<a href="{{ obj.cert.url }}" download="{{ obj.cert.name }}">下载文件</a>
方案2:视图处理下载(适合需要权限控制、隐藏真实文件地址的场景)
1. 新增下载视图
在对应app的views.py中添加下载逻辑:
from django.http import HttpResponse, Http404 from django.shortcuts import get_object_or_404 from django.utils.encoding import escape_uri_path import mimetypes from .models import Certificate def download_certificate(request, cert_id): cert_obj = get_object_or_404(Certificate, id=cert_id) if not cert_obj.cert: raise Http404("文件不存在") # 二进制模式打开文件 with open(cert_obj.cert.path, 'rb') as f: mime_type, _ = mimetypes.guess_type(cert_obj.cert.path) response = HttpResponse(f, content_type=mime_type) # escape_uri_path处理中文文件名乱码问题 response['Content-Disposition'] = f"attachment; filename={escape_uri_path(cert_obj.cert.name)}" return response
2. 配置下载路由
在urls.py中添加路由规则:
path('download/cert/<int:cert_id>/', download_certificate, name='download_cert'),
3. 模板调用
<a href="{% url 'download_cert' obj.id %}">下载文件</a>
排查建议
如果修改后仍然下载到HTML文件,按F12打开浏览器调试工具,查看网络请求的响应内容:
- 如果是404页面:检查路由配置、文件是否真实存在
- 如果是登录页面:说明下载路由需要登录权限,添加对应权限校验即可
内容的提问来源于stack exchange,提问作者Biju
相关产品推荐
相关产品推荐

