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

Node.js中实现目录不存在则创建并保存前端传来的文件

Node.js 实现目录自动创建并保存前端上传文件

注意:你原代码里用了d.getDay(),这个方法返回的是星期几(0-6,0代表周日),不是当月的日期,应该改成d.getDate()来获取当月的具体日期(1-31),否则目录结构会不符合预期。

先给你修正后的目录生成代码:

const fs = require('fs');
const d = new Date();
// 修正日期获取逻辑,生成按年/月/日/时/分/秒分层的目录
const directory = `./some-dir/${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')}/${d.getHours()}/${d.getMinutes()}/${d.getSeconds()}`;
// 递归创建目录,不存在则自动生成父目录
fs.mkdirSync(directory, { recursive: true });

下面分两种常见场景给出文件保存的实现方案:

场景1:基于 Express + Multer 处理文件上传(最常用)

Multer是Express生态中专门处理multipart/form-data类型请求的库,适合快速实现文件上传功能。

  1. 安装依赖:
npm install express multer
  1. 完整代码示例:
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const app = express();

// 配置Multer的存储规则
const storage = multer.diskStorage({
  // 动态设置文件存储目录
  destination: (req, file, cb) => {
    const d = new Date();
    const directory = `./some-dir/${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')}/${d.getHours()}/${d.getMinutes()}/${d.getSeconds()}`;
    // 确保目录存在
    fs.mkdirSync(directory, { recursive: true });
    cb(null, directory);
  },
  // 自定义文件名,避免重复覆盖
  filename: (req, file, cb) => {
    // 生成唯一后缀,保留原文件扩展名
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    const ext = file.originalname.split('.').pop();
    cb(null, `${file.fieldname}-${uniqueSuffix}.${ext}`);
  }
});

// 初始化Multer实例
const upload = multer({ storage: storage });

// 处理单文件上传接口,前端表单的file字段名需为'uploadedFile'
app.post('/upload', upload.single('uploadedFile'), (req, res) => {
  res.status(200).send(`文件已成功保存至:${req.file.path}`);
});

// 启动服务器
app.listen(3000, () => {
  console.log('服务器运行在 http://localhost:3000');
});

场景2:原生Node.js 处理文件上传(无框架)

如果不用Express等框架,可以用formidable库手动解析上传的表单数据。

  1. 安装依赖:
npm install formidable
  1. 完整代码示例:
const http = require('http');
const formidable = require('formidable');
const fs = require('fs');

const server = http.createServer((req, res) => {
  // 处理上传请求
  if (req.url === '/upload' && req.method.toLowerCase() === 'post') {
    const form = formidable({ multiples: false });

    form.parse(req, (err, fields, files) => {
      if (err) {
        res.writeHead(400, { 'Content-Type': 'text/plain' });
        res.end(`解析表单失败:${err.message}`);
        return;
      }

      const uploadedFile = files.uploadedFile;
      // 生成目标目录
      const d = new Date();
      const directory = `./some-dir/${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')}/${d.getHours()}/${d.getMinutes()}/${d.getSeconds()}`;
      fs.mkdirSync(directory, { recursive: true });

      // 构造目标文件路径
      const targetPath = `${directory}/${uploadedFile.originalFilename}`;
      // 将临时文件移动到目标目录
      fs.rename(uploadedFile.filepath, targetPath, (moveErr) => {
        if (moveErr) {
          res.writeHead(500, { 'Content-Type': 'text/plain' });
          res.end(`保存文件失败:${moveErr.message}`);
          return;
        }
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end(`文件已成功保存至:${targetPath}`);
      });
    });
    return;
  }

  // 返回简单的上传表单页面
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end(`
    <form action="/upload" method="post" enctype="multipart/form-data">
      <input type="file" name="uploadedFile" required>
      <button type="submit">上传文件</button>
    </form>
  `);
});

server.listen(3000, () => {
  console.log('服务器运行在 http://localhost:3000');
});

额外注意事项

  • 权限问题:确保Node.js进程对目标目录拥有读写权限,否则会抛出权限错误。
  • 异步优化:如果担心同步创建目录阻塞事件循环,可以改用fs.promises.mkdir异步方法,配合async/await使用。
  • 文件名冲突:如果前端可能上传相同文件名的文件,一定要添加唯一标识(如时间戳、随机字符串)避免文件被覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 08:05:24