如何开发功能类似Python内置SimpleHTTPServer的Django file explorer
Django 类SimpleHTTPServer文件浏览器实现方案
1. 基础依赖与模型搭建
- 首先安装必要依赖:
pip install django django-ranged-response,其中django-ranged-response用于处理大文件断点续传,匹配原生SimpleHTTPServer的文件访问体验 - 角色权限配置:
- 基于Django自带Auth系统扩展用户表,新增
role字段,可选值为TEST/ITOPS/ADMIN等自定义角色 - 新增目录权限映射模型
DirectoryPermission,核心字段如下:role:字符类型,对应用户角色allowed_path:字符类型,存储该角色允许访问的相对根目录的路径can_download:布尔值,默认True,可扩展控制文件下载权限
- 基于Django自带Auth系统扩展用户表,新增
- 全局配置:在
settings.py中新增配置项FILE_EXPLORER_ROOT = "/your/root/directory",作为所有可访问目录的父级根目录,避免路径穿越风险
2. 核心视图逻辑开发
核心逻辑参考示例如下:
import os from django.conf import settings from django.http import HttpResponse, Http404, HttpResponseForbidden from django.contrib.auth.decorators import login_required from .models import DirectoryPermission @login_required def file_explorer(request, req_path=""): # 第一步:路径规范化,防止穿越 full_path = os.path.normpath(os.path.join(settings.FILE_EXPLORER_ROOT, req_path)) if not full_path.startswith(settings.FILE_EXPLORER_ROOT): return HttpResponseForbidden("非法路径访问") # 第二步:角色权限校验 user_role = request.user.role allowed_paths = DirectoryPermission.objects.filter(role=user_role).values_list("allowed_path", flat=True) has_access = False for allowed_path in allowed_paths: allowed_full = os.path.normpath(os.path.join(settings.FILE_EXPLORER_ROOT, allowed_path)) + os.sep if full_path.startswith(allowed_full) or full_path == allowed_full.rstrip(os.sep): has_access = True break if not has_access: return HttpResponseForbidden("无当前目录访问权限") # 第三步:匹配SimpleHTTPServer逻辑处理请求 if os.path.isdir(full_path): # 优先返回目录下的index.html index_path = os.path.join(full_path, "index.html") if os.path.exists(index_path) and os.path.isfile(index_path): with open(index_path, "rb") as f: return HttpResponse(f.read(), content_type="text/html") # 无index.html则渲染目录列表 file_list = os.listdir(full_path) # 此处自行实现目录列表页渲染,展示文件名、修改时间、大小等信息即可 return render(request, "dir_list.html", {"file_list": file_list, "current_path": req_path}) elif os.path.isfile(full_path): # 过滤敏感文件 forbidden_suffix = [".py", ".env", ".git", ".sql"] if any(full_path.endswith(suf) for suf in forbidden_suffix): return HttpResponseForbidden("该文件禁止访问") # 返回文件内容,大文件可使用ranged response做流式响应 with open(full_path, "rb") as f: content_type = "application/octet-stream" if full_path.endswith(".html"): content_type = "text/html" return HttpResponse(f.read(), content_type=content_type) else: raise Http404("请求路径不存在")
3. 路由配置
在urls.py中添加通配路由,匹配任意层级的访问路径:
urlpatterns = [ # 其他原有路由 path("explorer/<path:req_path>", file_explorer, name="file_explorer"), # 根路径访问默认指向explorer根目录 path("", file_explorer, {"req_path": ""}, name="explorer_root"), ]
开发建议
安全优化
- 所有用户传入的路径必须做规范化处理,禁止直接拼接路径后读取文件,避免
../形式的路径穿越漏洞 - 敏感文件/目录统一过滤,除了代码示例中的后缀,还可以根据业务需求新增禁止访问的路径规则
- 静态HTML文件直接返回原始内容即可,不要走Django模板渲染逻辑,避免植入的模板语法被执行产生XSS漏洞
体验优化
- 目录列表页可新增按文件名、修改时间、文件大小排序的功能,比原生SimpleHTTPServer更易用
- 超过100M的大文件使用流式响应返回,不要一次性读入内存,避免服务器内存溢出
- 可新增文件搜索功能,支持对当前目录下的文件做名称模糊匹配
扩展建议
- 如果后续角色数量增加,可以直接对接Django自带的权限组系统,不需要硬编码角色字段,灵活性更高
- 新增访问日志功能,记录每个用户的访问路径、访问时间、客户端IP,满足审计需求
- 如需扩展上传功能,额外新增上传权限校验即可,默认只读模式和原生SimpleHTTPServer能力对齐
内容的提问来源于stack exchange,提问作者starterfor10
相关产品推荐
相关产品推荐

