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

multer按函数参数设置动态文件夹/文件名上传的TS报错求助

错误原因

你当前导出的upload是一个接收foldername、filename参数、返回Multer实例的工厂函数,不是Multer实例本身,直接调用upload.array相当于在函数类型上调用Multer实例的方法,自然会触发类型报错。

解决方案

方案1:路由层指定固定存储路径(符合你不想从req取参数的需求)

如果不同路由对应固定的存储文件夹/文件名规则,直接在注册路由时传入参数执行upload函数,拿到Multer实例后再调用array方法即可,修改file.ts路由代码:

import { Router } from 'express';
import fileController from '../controllers/file';
import upload from '../middlewares/upload';

const router = Router();

// 示例:上传文件统一存到upload_files文件夹,文件名可自定义,你可以替换为自己的业务参数
router.post('/upload', upload('upload_files', '自定义文件名').array("files"), fileController.upload);
router.get('/', fileController.getFileNames);
router.get('/:foldername/:filename', fileController.download);
 
export default router;

额外优化建议

你当前的写法会让同一接口上传的所有文件共用同一个文件名,会出现文件覆盖问题,建议调整upload.ts的命名逻辑,保留原文件名后缀或者拼接文件唯一标识:

import multer from 'multer';
import multerS3 from 'multer-s3';
import { v4 as uuidv4 } from 'uuid'; // 安装依赖:npm i uuid @types/uuid

import s3 from '../config/s3';

const upload = (foldername: string, filenamePrefix?: string) => {
    return multer({
        storage: multerS3({
            s3: s3,
            bucket: '你的S3桶名', // 补全实际的S3存储桶名称
            key: function (req: any, file: Express.Multer.File, cb: (error: any, key?: string) => void) {
                // 拼接前缀+唯一标识+原文件后缀,避免重名覆盖
                const suffix = file.originalname.split('.').pop();
                const finalFilename = `${filenamePrefix || ''}${uuidv4()}.${suffix}`;
                const fullPath = `${foldername}/${finalFilename}`;
                cb(null, fullPath);
            }
        })
    });
}

export default upload;

如果确实需要根据请求动态指定文件夹/文件名,可以在key方法中从req的查询参数/请求体中取值,需要注意普通表单参数要放在文件上传参数之前,multer才能正确解析到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:48:02