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

实现支持文件夹上传的Dropzone:表单为空问题求解

解决Dropzone文件夹上传表单为空的问题

问题根源

  • 异步操作时序错误:entry.file()是异步方法,循环结束后立即发送请求时,文件还未被添加到FormData,导致表单为空。
  • 未处理文件夹递归:原代码仅判断文件项,未遍历文件夹内的子文件/子文件夹,无法实现文件夹上传。
  • 路径拼接错误:file.webkitRelativePath已包含完整相对路径(含文件名),额外拼接file.name会导致路径重复。

修改后的实现代码

dropZone.addEventListener('drop', function(e) {
    e.preventDefault();
    hideDropZone();
    const items = e.dataTransfer.items;
    uploadFiles(items);
});

// 递归遍历文件/文件夹,收集所有文件的Promise
async function collectFiles(entry) {
    const files = [];
    if (entry.isFile) {
        return new Promise(resolve => {
            entry.file(file => {
                files.push({ file, path: file.webkitRelativePath });
                resolve(files);
            });
        });
    } else if (entry.isDirectory) {
        const reader = entry.createReader();
        return new Promise((resolve, reject) => {
            function readEntries() {
                reader.readEntries(async (entries) => {
                    if (entries.length === 0) {
                        resolve(files);
                        return;
                    }
                    for (const subEntry of entries) {
                        const subFiles = await collectFiles(subEntry);
                        files.push(...subFiles);
                    }
                    readEntries(); // 处理readEntries分批返回的目录项
                }, reject);
            }
            readEntries();
        });
    }
    return files;
}

async function uploadFiles(items) {
    const formData = new FormData();
    const allFiles = [];

    for (const item of items) {
        const entry = item.webkitGetAsEntry();
        if (entry) {
            const files = await collectFiles(entry);
            allFiles.push(...files);
        }
    }

    allFiles.forEach(({ file, path }) => {
        formData.append('files', file, path);
    });

    const request = new XMLHttpRequest();
    request.open('POST', `/u?d=${get('d')}`);
    request.send(formData);
}

关键修改说明

  • 异步时序修正:使用async/await和Promise确保所有文件都添加到FormData后再发送请求。
  • 文件夹递归遍历:新增collectFiles函数,递归处理文件夹内所有子项,实现完整的文件夹内容收集。
  • 路径参数修正:直接使用file.webkitRelativePath作为FormData.append的第三个参数,保证文件路径正确。
  • 完善目录读取:处理readEntries分批返回目录项的情况,确保所有子文件/文件夹都被遍历到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:57:46