Django中如何实现input type file直接上传文件夹而非多选文件
Django实现input文件控件直接上传整个文件夹
整个实现分前端配置和后端接收两部分,不需要额外引入第三方上传组件,用原生控件就能实现。
前端模板配置
原生input[type=file]本身就支持文件夹选择,只需要给控件加3个属性即可:
webkitdirectory:Chrome/Edge等webkit内核浏览器识别的文件夹选择属性directory:Firefox等非webkit内核浏览器识别的同功能属性multiple:支持多文件读取,保证能拿到文件夹下所有层级的文件
表单代码示例:
<form method="POST" enctype="multipart/form-data" action="/your/upload/path/"> {% csrf_token %} <input type="file" name="folder_upload" webkitdirectory directory multiple accept="image/*,.pdf,.doc"> <button type="submit">选择文件夹上传</button> </form>
上面的
accept属性可以按需配置,用来过滤文件夹内需要上传的文件类型,比如只传图片就写image/*。
用户点击这个控件弹出的系统选择框,会默认只允许选中文件夹,选中后浏览器会自动递归读取文件夹下所有子文件,不需要用户手动逐个选文件。每个文件会自带原文件夹内的相对路径标识,后端可以靠这个字段还原原有的目录结构。
如果需要做前端预校验、进度展示,可以通过JS拿到文件列表:
const fileInput = document.querySelector('input[name="folder_upload"]'); fileInput.addEventListener('change', e => { const allFiles = e.target.files; console.log(`当前选中文件夹共包含${allFiles.length}个文件`); // 遍历拿到每个文件的相对路径,比如"旅行照片/三亚/IMG_001.jpg" for (const file of allFiles) { console.log(file.webkitRelativePath); } })
Django后端处理逻辑
后端接收逻辑和普通多文件上传的核心区别是,必须用getlist方法取文件列表,不能直接用键名取单个文件,同时要根据文件自带的相对路径创建对应目录,还原原文件夹结构。
视图函数示例:
import os from django.conf import settings from django.http import JsonResponse from django.views.decorators.csrf import csrf_protect @csrf_protect def folder_upload_view(request): if request.method != "POST": # 自行处理GET请求的页面渲染逻辑 return render(request, "upload_page.html") # 核心:用getlist获取所有上传的文件对象 uploaded_files = request.FILES.getlist("folder_upload") # 定义文件夹上传的根存储路径 save_root = os.path.join(settings.MEDIA_ROOT, "user_upload_folders") os.makedirs(save_root, exist_ok=True) for file in uploaded_files: # file.name就是文件在原文件夹内的相对路径,直接用来拼存储路径 full_save_path = os.path.join(save_root, file.name) # 自动创建路径中不存在的父级目录 os.makedirs(os.path.dirname(full_save_path), exist_ok=True) # 分块写入文件,避免大文件占满内存 with open(full_save_path, "wb+") as f: for chunk in file.chunks(): f.write(chunk) return JsonResponse({"code": 0, "msg": f"上传完成,共处理{len(uploaded_files)}个文件"})
常见踩坑点
- 兼容性:该特性支持所有主流桌面端浏览器(Chrome/Edge/Firefox/Safari 11.1+),移动端浏览器兼容性较差,面向C端移动端用户需要做降级提示
- 配置调整:如果要上传包含大量文件的文件夹,需要修改Django配置:把
DATA_UPLOAD_MAX_NUMBER_FILES(Django 3.2+版本生效,默认值1000)调大到匹配业务需求,同时按需调大FILE_UPLOAD_MAX_MEMORY_SIZE参数;如果服务前挂了Nginx等反向代理,也要同步调大client_max_body_size参数,避免请求被拦截 - 安全校验:前端的
accept属性只能防普通误操作,后端必须做二次校验,检查文件后缀、MIME类型、文件大小,拦截恶意脚本等非法文件 - 异步上传:如果要做无刷新上传、上传进度条,直接用FormData对象包裹文件列表发异步请求即可,逻辑和普通多文件上传完全一致
内容的提问来源于stack exchange,提问作者Zouhaira Ayari
相关产品推荐
相关产品推荐

