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

如何在Django中实现Windows服务器共享文件的下载功能?

问题:Django应用中实现Windows共享文件的正常下载链接

背景

  • 开发的Django应用展示工单查询结果,包含指向Windows服务器共享目录的文件下载链接,路径格式为\\server.name\folder A\folder B\folder C\待下载文件.txt
  • 固定路径部分:\\server.name\folder A\folder B
  • 动态内容:\folder C及待下载文件名
  • 所有文件已存储在Windows共享目录,无需用户上传

当前问题

模板页面中表格内的下载链接,鼠标悬停时浏览器显示路径为file://server.name/folder A/folder B\\folder C\\file to download.txt,斜杠格式混乱;传递到模板的原始路径是\\server.name\\folder A\\folder B\\folder C\\file to download.txt,点击链接无法正常下载文件。

相关代码

模板文件(ticket.html)

<body>

<h1><p>Ticket Number: {{ thisincident.IncidentID }}</p></h1>
<h3>Description: {{ thisincident.Description }}</h3>
<h4><p>Full Description</h4> {{ thisincident.FullDescription | linebreaks }}</p>

<table>
    <thead>
        <tr>
            <th>Journal Entry #</th>
            <th>Date</th>
            <th>Person</th>
            <th>Journal Entry</th>
            <th>File Name</th>
        </tr>
    </thead>
    <tbody>
    {% for f in je %}
    <tr>
       <td>{{ f.JE }}</td>
       <td>{{ f.Date }}</td> 
       <td>{{ f.resource }}</td>
       <td>{{ f.entry | linebreaks }}</td>
       <td><a href="{{ f.Location }}">Download</a></td>
    </tr>
    {% endfor %}
    </tbody>
</table>
</body>

views.py

def ticket_view(request, IncidentID):
    file_contents = []
    thisincident = ticket.objects.get(id=IncidentID)
    for root, dirs, files in os.walk(thisincident.LocationPath):
        for file in files:
            if not file == 'manifest.json':
                path_file = os.path.join(root, file)
                path_file = path_file.replace(thisincident.LocationPath + "\\", "")
                file_contents.append(path_file)
    log_list = parseJElog(thisincident.logfiletoparse)

    data = {
        "thisincident": thisincident,
        "result": file_contents,
        "je":log_list
    }
    return render(request, "ticket.html", data)

urls.py

urlpatterns = [
    url(r'^homepage/$', views.home, name='home'),
    url(r'^tickets/$', views.tickets, name='tickets'),
    url(r'^ticket/(?P<IncidentID>\d+)$', views.ticket_view, name='ticket'),
]
if settings.DEBUG:
    urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings.py

MEDIA_BASE_ROOT = "\\server.name\\folder A\\folder B"
MEDIA_ROOT = os.path.join(MEDIA_BASE_ROOT, "\\folder B\\")
MEDIA_URL = ''

解决方案

核心问题分析

直接使用file://协议访问Windows共享文件会触发浏览器安全策略拦截,同时存在跨域限制和路径格式混乱问题。正确做法是通过Django后端作为代理,读取共享文件后返回给用户,而非直接暴露共享路径。

步骤1:新增下载处理视图

在views.py中添加专门处理文件下载的视图,统一路径格式并做安全校验:

import os
from django.http import FileResponse, Http404
from django.conf import settings

def download_shared_file(request, IncidentID, file_path):
    # 拼接完整共享路径,统一格式
    full_path = os.path.normpath(os.path.join(settings.MEDIA_BASE_ROOT, file_path))
    
    # 校验文件合法性,防止目录遍历攻击
    if not os.path.exists(full_path) or not os.path.isfile(full_path):
        raise Http404("文件不存在")
    
    # 返回文件下载响应
    response = FileResponse(open(full_path, 'rb'))
    response['Content-Disposition'] = f'attachment; filename="{os.path.basename(full_path)}"'
    return response

步骤2:配置下载路由

在urls.py中添加下载路由,支持动态文件路径:

urlpatterns = [
    url(r'^homepage/$', views.home, name='home'),
    url(r'^tickets/$', views.tickets, name='tickets'),
    url(r'^ticket/(?P<IncidentID>\d+)$', views.ticket_view, name='ticket'),
    # 新增下载路由,匹配任意子路径
    url(r'^ticket/(?P<IncidentID>\d+)/download/(?P<file_path>.*)$', views.download_shared_file, name='download_shared_file'),
]

步骤3:修改模板链接

将模板中的直接路径替换为Django反向解析的URL:

<td><a href="{% url 'download_shared_file' IncidentID=thisincident.IncidentID file_path=f.Location %}">Download</a></td>

步骤4:优化路径处理(可选)

在ticket_view中确保传递给模板的是相对正斜杠路径,避免转义问题:

# 替换原路径处理逻辑
path_file = os.path.relpath(os.path.join(root, file), settings.MEDIA_BASE_ROOT)
path_file = path_file.replace(os.sep, '/')
file_contents.append(path_file)

关键注意事项

  • 权限配置:确保Django运行账户拥有Windows共享目录的访问权限(需配置共享权限和NTFS权限)
  • 安全防护:通过os.path.normpath和存在性检查,阻断目录遍历攻击
  • 跨平台兼容:统一使用正斜杠路径,避免Windows与Web路径格式冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:24:58