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

Node.js TypeScript下Multer上传文件到GCP存储桶chunk类型报错

问题根因

报错核心原因是流初始化参数传错:
代码中streamifier.createReadStream()传入的是documentFile.buffer.length,这是一个代表文件字节长度的数字类型值,而非Multer解析出来的实际文件Buffer对象。读取流启动后会直接把这个数字作为数据块推送给GCS的写入流,而GCS写入流只接受字符串或Buffer类型的写入块,因此直接抛出参数类型错误。
另外代码里还有一个隐藏bug:finish事件的回调参数被命名为res,会覆盖外层Express框架的响应对象res,即使上传成功也会因为调用了错误对象的status/json方法触发新的异常。

修正后代码
try {
  const documentFile = (req as MulterRequest).file;
  const blob = bucket.file(documentFile.originalname);
  // 建议写入时配置对应文件的MIME类型,避免上传后文件元信息错误
  const blobStream = blob.createWriteStream({
    contentType: documentFile.mimetype
  });

  blobStream.on("error", (err: any) => {
    return res.status(500).send({ message: err.message });
  });

  // 修正:传入实际文件Buffer,而非Buffer的长度数值
  streamifier.createReadStream(documentFile.buffer)
    .on('error', (e: any) => {
      console.log("file read error");
      console.log(e);
      next(e);
    })
    .pipe(blobStream)
    // 修正:移除回调里和外层res重名的参数,避免变量覆盖
    .on('finish', () => {
      console.log("upload success");
      return res.status(200).json({
        message: 'Upload user document successfully',
        data: documentFile
      });
    });
} catch (e) {
  next(e);
}
可选优化建议
  • 如果不需要对流做额外的转换/处理逻辑,可以完全去掉streamifier依赖,直接调用GCS File对象的save方法写入Buffer,代码更简洁:
    await blob.save(documentFile.buffer, {
      contentType: documentFile.mimetype
    });
    
  • 上传前建议对文件名做重命名处理(比如拼接UUID),避免不同用户上传同名文件时出现覆盖问题
  • 生产环境建议给GCS写入操作配置超时、重试策略,提升上传稳定性

内容的提问来源于stack exchange,提问作者WEI ZHUANG GOH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:21:29