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

Docker部署Django应用后download属性失效,如何解决文件下载异常?

Django Docker部署后文件下载失效的解决方法

问题根源

本地开发时Django自带的服务器会自动处理媒体文件请求,但生产环境用gunicorn作为WSGI服务器时,默认不负责静态/媒体文件的路由;同时你的路径配置错误,把容器内部的绝对路径传给了前端,导致Web服务器无法找到目标文件,最终返回当前网页副本。

修复步骤

1. 修正Django媒体文件核心配置

在项目的settings.py中,确保正确设置媒体文件的存储根目录和访问URL:

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 媒体文件配置
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

2. 修正视图中的路径生成逻辑

在main/views.py中,使用Django配置的MEDIA_URL生成前端可访问的路径,而非容器内部的/app路径:

from django.conf import settings
import os

# 生成文件名和相对路径
report_filename = f"{request.user.username}{now.hour}{now.minute}{now.second}.txt"
report_relative_path = f"Reports/{request.user.username}/{report_filename}"
# 生成Web可访问的完整URL
path_to_report = f"{settings.MEDIA_URL}{report_relative_path}"

# 确保存储目录存在,避免写入失败
full_file_path = os.path.join(settings.MEDIA_ROOT, report_relative_path)
os.makedirs(os.path.dirname(full_file_path), exist_ok=True)
# 此处写入文件内容到full_file_path

# 传递正确路径到模板
return render(request, "main/result.html", {
    "dic_files": dic_files,
    "nbr": len(files),
    "dic_small": dic_small,
    "dic_projects": dic_projects,
    "path_to_report": path_to_report
})

3. 修正模板中的下载链接

在main/result.html中,直接使用视图传递的路径,无需额外添加斜杠:

<a href="{{ path_to_report }}" download>
    <button class="btn btn-success" name="rapport" value="rapport"> Télécharger votre rapport</button>
</a>

4. 处理生产环境媒体文件服务

gunicorn不负责静态/媒体文件的请求处理,需选以下方案之一配置:

方案A:用WhiteNoise处理媒体文件

适合小型应用,无需额外反向代理:

  1. 安装WhiteNoise:
pip install whitenoise
  1. 在settings.py中修改配置:
INSTALLED_APPS = [
    'whitenoise.runserver_nostatic',
    'django.contrib.staticfiles',
    # 其他应用...
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    # 其他中间件...
]

# 允许WhiteNoise处理媒体文件
WHITENOISE_USE_FINDERS = True
WHITENOISE_MEDIA_PREFIX = '/media/'

方案B:用Nginx反向代理处理媒体文件

适合流量较大的应用,配置Nginx直接接管媒体文件请求:

server {
    listen 80;
    server_name your-domain.com;

    # 直接处理媒体文件请求
    location /media/ {
        alias /app/media/; # 容器内的媒体目录路径
        expires 30d;
    }

    # 其他请求转发给gunicorn
    location / {
        proxy_pass http://gunicorn:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

5. 优化Docker配置

在Dockerfile中添加媒体目录权限设置,确保Django有写入权限:

# ... 现有内容 ...

RUN python manage.py collectstatic --no-input

# 创建媒体目录并设置权限
RUN mkdir -p media/Reports && chmod -R 755 media

ENTRYPOINT ["gunicorn", "myteam.wsgi:application", "--bind=0.0.0.0:8000", "--workers=4", "--timeout=300", "--log-level=debug"]

另外建议将数据库迁移命令从镜像构建阶段移到容器启动时,避免镜像绑定特定数据库状态:
创建entrypoint.sh脚本:

#!/bin/bash
python manage.py makemigrations
python manage.py migrate
exec gunicorn myteam.wsgi:application --bind=0.0.0.0:8000 --workers=4 --timeout=300 --log-level=debug

修改Dockerfile:

# ... 现有内容 ...

RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:57:29