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

