使用Express搭配Multer-S3直传S3时PDF等非SVG文件无法打开如何解决
问题原因及修复方案
1. 核心问题:multer-s3-transform 无转换配置导致二进制文件损坏
你当前使用的multer-s3-transform库核心功能是支持上传时对文件做格式转换,如果没有显式配置transform选项,库会默认对非文本类二进制文件做错误的编码处理,所以SVG这种文本类矢量文件可以正常上传,PDF、图片等二进制文件会被篡改损坏。
修复方案二选一:
- 方案1:替换为普通版multer-s3(不需要转换功能的话优先选这个)
先卸载当前库:npm uninstall multer-s3-transform
安装官方普通版:npm install multer-s3
原filesService.js里的存储配置不需要改动,普通版multer-s3和当前代码的API完全兼容。 - 方案2:保留multer-s3-transform,补充空转换配置
在multerS3配置里补充transforms选项,配置直接返回原文件流即可,修改后的配置片段如下:storage: multerS3({ acl: "public-read", s3: s3, bucket: BUCKET_NAME, contentType: multerS3.AUTO_CONTENT_TYPE, // 新增transform配置 transforms: [ { id: 'original', key: (req, file, cb) => cb(null, file.originalname), transform: (req, file, cb) => cb(null, require('stream').PassThrough()) } ] })
2. 路由逻辑错误修复
当前路由代码存在两个问题:
multer.upload是回调风格的函数,不返回Promise,加await完全无效- 上传逻辑执行后不管是否成功,都会走到外层的
res.status(500),会导致即使上传成功,响应状态也可能被篡改,甚至触发重复设置响应头的报错
修复后的route.js代码:
router.post('/files', (req, res ,next) => { filesService.upload(req, res, (err) => { if(err) { console.error(err); return res.status(500).send({error: '文件上传失败'}); } console.log(req.file); res.status(200).send({link: req.file.location}); }); })
3. 可选校验配置
如果还有异常可以补充文件类型过滤,避免非法文件上传,在multer配置里增加fileFilter选项即可:
const upload = multer({ limits: limits, // 新增文件类型过滤 fileFilter: (req, file, cb) => { const allowedTypes = ['application/pdf', 'image/svg+xml', 'image/jpeg', 'image/png']; if(allowedTypes.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('不支持的文件类型'), false); } }, storage: multerS3({ // 原有存储配置保持不变 }) }).single('file');
内容的提问来源于stack exchange,提问作者Raz Levy
相关产品推荐
相关产品推荐

