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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:06:25