Multer S3上传异常:MP4文件体积变大且无法播放
问题:MP4文件上传至S3后体积变大且无法播放
通过Node.js结合S3上传MP4文件,执行代码后S3中能看到目标文件,但原文件大小为860kb,上传后变为1.4MB,下载后无法正常播放。相关代码如下:
Setup 代码
const storageS3: StorageEngine = multer.memoryStorage(); const uploadS3 = multer({ storage: storageS3 });
Upload 代码
const s3Upload = async (req: Request, res: Response, next: NextFunction) => { const files = req.files as Express.Multer.File[]; const uploadPromises = files.map(async (file) => { const params = { Bucket: process.env.S3_BUCKET_NAME!, Key: `uploads/${file.originalname}`, Body: file.buffer, ContentType: "video/mp4", // for test purposes }; return s3.upload(params).promise(); }); try { await Promise.all(uploadPromises); next(); } catch (err) { next(err); } };
Route Middleware 代码
const determineUploadHandler = async ( req: Request, res: Response, next: NextFunction ) => { if (isLocal) { upload.array("media")(req, res, next); } else { logFileSizeBeforeMulter(req, res, () => { uploadS3.array("media")(req, res, async (err) => { if (err) return next(err); await s3Upload(req, res, next); }); }); } };
Route 代码
export const uploadHandler = router.post( "/", determineUploadHandler, (req: Request, res: Response) => { res.status(200).json({ message: "Files uploaded successfully" }); } );
文件信息对比
- 原文件:大小860kb,MP4格式
- S3中文件:大小1.4MB,下载后无法播放
问题原因及修复方案
核心问题:二进制数据处理异常
上传后文件体积变大且损坏,大概率是Multer读取文件或S3上传时,二进制数据被错误编码(比如当成文本格式处理),导致原始字节流被篡改。
修复步骤:
规范Multer的文件处理配置
初始化multer时,明确限制文件类型、大小,并确保二进制数据的正确读取:const uploadS3 = multer({ storage: storageS3, limits: { fileSize: 10 * 1024 * 1024 }, // 根据业务需求调整大小限制 fileFilter: (req, file, cb) => { // 仅允许MP4文件上传 if (file.mimetype === 'video/mp4') { cb(null, true); } else { cb(new Error('仅支持MP4格式视频文件')); } } });完善S3上传参数
不要硬编码ContentType,改用Multer识别的文件类型;同时明确设置ContentLength,避免S3自动编码错误:const s3Upload = async (req: Request, res: Response, next: NextFunction) => { const files = req.files as Express.Multer.File[]; const uploadPromises = files.map(async (file) => { // 日志验证文件大小是否匹配本地文件 console.log(`本地文件大小: ${file.size} bytes`); const params = { Bucket: process.env.S3_BUCKET_NAME!, Key: `uploads/${file.originalname}`, Body: file.buffer, ContentType: file.mimetype, // 使用Multer解析的真实MIME类型 ContentLength: file.size, // 明确指定文件字节长度 }; // 可选:改用putObject更可控,避免upload的自动编码逻辑 return s3.putObject(params).promise(); }); try { await Promise.all(uploadPromises); next(); } catch (err) { next(err); } };排查前端上传逻辑
确保前端使用multipart/form-data格式上传文件,不要将文件转成base64编码后再上传——base64编码会让文件体积增大约33%,且会破坏原始二进制结构,导致视频无法播放。验证文件完整性
上传完成后,对比S3文件的Content-Length和本地文件的字节数,如果数值一致,说明上传流程正常;若不一致,重点排查Multer读取阶段或前端传输阶段的编码问题。
内容的提问来源于stack exchange,提问作者ThunD3eR
相关产品推荐
相关产品推荐

