如何使用Node.js Multer实现文件夹上传?配合react-dropzone的方案
实现可行性结论
完全可以实现该需求。整体实现逻辑是前端通过react-dropzone获取文件夹内所有文件的完整相对路径,随文件一同传到后端;后端用Multer接收文件后,按照相对路径创建对应目录层级存储文件,就能完整还原原文件夹结构,不需要提前打包zip。
前端实现(基于react-dropzone)
- 首先安装依赖:
npm install react-dropzone - 配置dropzone开启文件夹选择能力,通过浏览器原生
webkitRelativePath属性获取每个文件在原文件夹中的相对路径,用FormData提交到后端:
import { useDropzone } from 'react-dropzone'; function FolderUploader() { const { getRootProps, getInputProps } = useDropzone({ // 开启文件夹选择模式 webkitdirectory: true, directory: true, onDrop: (acceptedFiles) => { const formData = new FormData(); // 遍历文件夹下所有文件加入FormData acceptedFiles.forEach(file => { // 第三个参数传入文件的相对路径,后端可直接读取 formData.append('folderFiles', file, file.webkitRelativePath); }); // 发送上传请求 fetch('/api/upload-folder', { method: 'POST', body: formData }).then(res => res.json()).then(data => { console.log('上传完成', data); }); } }); return ( <div {...getRootProps({style: {border: '2px dashed #ccc', padding: '20px'}})}> <input {...getInputProps()} /> <p>拖拽文件夹到此处上传,或点击选择文件夹</p> </div> ); } export default FolderUploader;
后端实现(基于Multer)
- 先安装依赖:
npm install express multer fs-extra,fs-extra用于简化多级目录创建逻辑 - 配置Multer存储规则,自动根据文件相对路径创建目录存储:
const express = require('express'); const multer = require('multer'); const fs = require('fs-extra'); const path = require('path'); const app = express(); // 配置Multer磁盘存储规则 const storage = multer.diskStorage({ destination: async (req, file, cb) => { // 拆分相对路径中的目录部分 const relativeDir = path.dirname(file.originalname); // 拼接本地存储的完整目录,默认存在项目根目录的uploads文件夹下 const uploadDir = path.join(__dirname, 'uploads', relativeDir); // 递归创建目录,不存在则自动新建 await fs.mkdirs(uploadDir); cb(null, uploadDir); }, filename: (req, file, cb) => { // 取原文件名作为存储文件名 const fileName = path.basename(file.originalname); cb(null, fileName); } }); // 初始化Multer实例,可根据业务调整大小、数量限制 const upload = multer({ storage: storage, limits: { fileSize: 1024 * 1024 * 100, // 单文件最大100M files: 1000 // 单次最多上传1000个文件 } }); // 上传接口,字段名需和前端FormData.append的第一个参数保持一致 app.post('/api/upload-folder', upload.array('folderFiles', 1000), (req, res) => { res.json({ code: 200, message: '文件夹上传成功', files: req.files }); }); app.listen(3001, () => { console.log('服务运行在3001端口'); });
注意事项
- 浏览器兼容性:
webkitRelativePath属性支持所有主流现代浏览器(Chrome、Edge、Firefox),IE浏览器不支持,如有兼容需求需额外做降级处理 - 路径安全:可增加路径校验逻辑,拦截包含
../的恶意路径,避免文件被存储到非预期目录 - 大文件夹优化:如果需要上传超大文件夹,可额外增加分片上传、断点续传逻辑,普通场景上述实现可直接使用
内容的提问来源于stack exchange,提问作者Avinash
相关产品推荐
相关产品推荐

