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

Multer中file.size未定义求助:多文件上传无法获取单个文件大小

问题:Multer filename中间件中无法获取单个文件的file.size?

我使用Multer处理多文件上传,在filename中间件中编写了如下代码:

filename: async (req, file, cb) => {
    console.log(Object.keys(file));
    ({ rows } = await db.query(`
    INSERT INTO public.files(
      uuid,
      nom,
      type,
      size
    )
    VALUES
    ($1, $2, $3, $4)
    RETURNING *`, [
      req.uuid,
      file.originalname,
      file.mimetype,
      file.size,
      // +req.headers["content-length"],
    ]));
    cb(null, uuid);
  },

问题在于file.size始终为undefined,我已确认发送文件前文件大小是存在的。通过console.log查看file对象的属性,仅包含'fieldname', 'originalname', 'encoding', 'mimetype'。若使用+req.headers["content-length"],获取的是整个请求的总大小而非单个文件的大小。请问为何无法获取单个文件大小?是无法实现还是存在未找到的配置项?


解决办法

核心原因是:Multer的filename钩子是在文件开始写入前触发的,此时文件还未被完全接收,file.size字段还未被计算填充,所以你在这个阶段拿不到单个文件的大小。

有两种可行的解决方式:

1. 挪到文件上传完成后处理数据库插入

在Multer处理完文件上传的路由回调里,req.files(多文件)或req.file(单文件)中的每个文件对象都会包含完整的size属性,此时再遍历文件执行数据库插入即可:

// 假设你用upload.array('files')处理多文件上传
app.post('/upload', upload.array('files'), async (req, res) => {
  try {
    for (const file of req.files) {
      await db.query(`
        INSERT INTO public.files(
          uuid,
          nom,
          type,
          size
        )
        VALUES
        ($1, $2, $3, $4)
        RETURNING *`, [
        req.uuid,
        file.originalname,
        file.mimetype,
        file.size,
      ]);
    }
    res.status(200).json({ message: '文件上传并入库成功' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

2. 先入库再更新文件大小(适合必须在filename阶段关联记录的场景)

如果业务上需要在filename阶段就生成关联的数据库记录,可以先插入一条size为null或默认值的记录,等文件上传完成后再通过唯一标识(比如你用的req.uuid)更新这条记录的size:

// filename钩子中先插入无size的记录
filename: async (req, file, cb) => {
  await db.query(`
    INSERT INTO public.files(
      uuid,
      nom,
      type,
      size
    )
    VALUES
    ($1, $2, $3, $4)
    RETURNING *`, [
    req.uuid,
    file.originalname,
    file.mimetype,
    null // 先设为null
  ]);
  cb(null, req.uuid); // 用uuid作为文件名,方便后续关联
},

// 路由回调中更新size
app.post('/upload', upload.array('files'), async (req, res) => {
  try {
    for (const file of req.files) {
      await db.query(`
        UPDATE public.files
        SET size = $1
        WHERE uuid = $2`, [
        file.size,
        file.filename // 因为filename设为了uuid,直接拿这个关联
      ]);
    }
    res.status(200).json({ message: '文件上传并更新成功' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

需要注意的是,Multer的版本差异可能带来细节变化,但核心逻辑一致:filename是前置钩子,仅负责生成文件名,此时文件还未完成传输,无法获取准确的单个文件大小。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:42:38