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
相关产品推荐
相关产品推荐

