使用dropzone.js拖拽上传文件夹结构时如何识别空文件夹触发事件
Dropzone.js 拖拽上传空文件夹检测实现方案
Dropzone 默认的目录遍历逻辑只会收集存在实际文件的路径,空文件夹因无关联 File 对象会被直接跳过,不会触发内置回调,可通过重写目录遍历逻辑实现空文件夹检测,具体实现如下:
- 核心原理:基于浏览器原生
FileSystemEntryAPI递归遍历拖拽/选中的目录节点,当读取FileSystemDirectoryEntry实例的子条目返回空数组时,即可判定该节点为空文件夹,触发自定义事件即可。 - 注意避坑:
FileSystemDirectoryEntry.createReader().readEntries()单次调用不会返回目录下全部条目,必须循环调用直到返回空数组,否则大目录场景会出现漏判。
具体实现代码
在Dropzone初始化时拦截drop/文件选择事件,替换默认遍历逻辑:
const uploader = new Dropzone("#your-dropzone-container", { url: "/your/upload/api", // 保留原有业务配置 init: function () { const dz = this; // 递归遍历条目,收集文件与空文件夹 async function traverseEntry(entry, basePath = "", emptyDirs = []) { const currentPath = basePath + entry.name; if (entry.isFile) { return new Promise(resolve => { entry.file(file => { file.relativePath = currentPath; resolve({ files: [file], emptyDirs }); }); }); } if (entry.isDirectory) { const reader = entry.createReader(); return new Promise(resolve => { const collectedEntries = []; const readBatch = () => { reader.readEntries(async entries => { if (entries.length === 0) { // 无任何子项,判定为空文件夹 if (collectedEntries.length === 0) { emptyDirs.push({ name: entry.name, path: currentPath + "/" }); resolve({ files: [], emptyDirs }); return; } // 递归处理子项 let allFiles = []; for (const subEntry of collectedEntries) { const res = await traverseEntry(subEntry, currentPath + "/", emptyDirs); allFiles = allFiles.concat(res.files); } resolve({ files: allFiles, emptyDirs }); } else { collectedEntries.push(...entries); readBatch(); } }); }; readBatch(); }); } return { files: [], emptyDirs }; } // 拦截拖拽事件,替换默认处理逻辑 this.on("drop", async e => { e.stopImmediatePropagation(); const items = e.dataTransfer.items; if (!items?.length) return; let fileList = []; let emptyFolderList = []; for (const item of items) { const entry = item.webkitGetAsEntry(); if (!entry) continue; const { files, emptyDirs } = await traverseEntry(entry); fileList = fileList.concat(files); emptyFolderList = emptyFolderList.concat(emptyDirs); } // 正常文件交给Dropzone处理 fileList.forEach(file => dz.addFile(file)); // 空文件夹触发自定义事件 if (emptyFolderList.length) dz.emit("emptyFoldersDetected", emptyFolderList); }); // 监听空文件夹事件,写自定义业务逻辑 this.on("emptyFoldersDetected", folders => { console.log("检测到空文件夹", folders); // 可在此处加弹窗提示、单独上传空文件夹标记等逻辑 }); } });
补充说明
如果需要兼容点击选择文件夹的场景,给上传组件的hidden file input绑定change事件,复用上述traverseEntry逻辑处理选中的文件条目即可。
不推荐通过上传完成后统计文件路径反推空文件夹的方案,该方案识别准确率低,且会浪费上传请求的带宽资源。
内容的提问来源于stack exchange,提问作者Carl
相关产品推荐
相关产品推荐

