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

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上传时,二进制数据被错误编码(比如当成文本格式处理),导致原始字节流被篡改。

修复步骤:

  1. 规范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格式视频文件'));
        }
      }
    });
    
  2. 完善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);
      }
    };
    
  3. 排查前端上传逻辑
    确保前端使用multipart/form-data格式上传文件,不要将文件转成base64编码后再上传——base64编码会让文件体积增大约33%,且会破坏原始二进制结构,导致视频无法播放。

  4. 验证文件完整性
    上传完成后,对比S3文件的Content-Length和本地文件的字节数,如果数值一致,说明上传流程正常;若不一致,重点排查Multer读取阶段或前端传输阶段的编码问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:15:55