Node.js上传Google Cloud Storage无报错但所有文件均为0字节问题
问题根因与解决方案
你遇到的Google Cloud Storage上传后文件为0字节的问题,90%以上的情况来源于上游文件解析中间件配置错误、写入流逻辑异常两类原因,对应修复方案如下:
1. 修复文件上传中间件配置
你代码中依赖req.file.buffer写入文件内容,如果你用的是常用的multer中间件处理上传,必须显式配置内存存储模式,默认的磁盘存储模式不会填充req.file.buffer字段,只会写入本地磁盘路径,此时你传入的是空值,自然会生成0字节文件。
正确的multer配置参考:
const multer = require('multer'); // 启用内存存储,才会生成req.file.buffer const uploadMid = multer({ storage: multer.memoryStorage(), // 可按需添加文件大小限制 limits: { fileSize: 10 * 1024 * 1024 } }) // 路由注册时绑定中间件,单文件上传字段名需和前端传的字段名一致 app.post('/upload', uploadMid.single('file'), upload)
2. 补全代码校验与流逻辑优化
2.1 校验buffer是否为空
在调用GCS写入流之前先校验buffer长度,提前定位上游问题:
if (req.file.buffer.length === 0) { return res.status(400).send('文件内容为空,请检查上传配置') }
2.2 修复未定义变量错误
你当前代码中blobStream.on('error', err => { next(err); });用到了next但未在upload函数入参中声明,会触发未定义错误导致流中断,可补充next入参或者直接抛出错误到外层catch处理。
2.3 异步流等待
当前upload是async函数,但内部的流操作为异步回调模式,没有等待完成就可能提前返回,建议封装为Promise确保写入完成后再返回响应,优化后完整代码参考:
const gc = new Storage({ keyFilename: path.join(__dirname, "../faslearn-ba6c817cfcea.json"), projectId: "faslearn" }); const bucket = gc.bucket('faslearn_files') const upload = async (req, res, next) => { try { if (!req.file) { res.status(400).send('No file uploaded.'); return; } // 校验文件内容非空 if (req.file.buffer.length === 0) { return res.status(400).send('上传文件内容为空'); } const blob = bucket.file(req.file.originalname); const blobStream = blob.createWriteStream({ resumable: false, gzip: true }); // 等待流写入完成 await new Promise((resolve, reject) => { blobStream.on('error', reject); blobStream.on('finish', resolve); blobStream.end(req.file.buffer); }); const publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`; res.status(200).send(publicUrl); } catch (err) { console.log("上传失败:", err); res.status(500).send({ message: `Could not upload the file: ${req.file.originalname}. ${err}`, }); } };
3. 可选排查项
如果上述修改后仍有问题,可先暂时关闭createWriteStream的gzip: true配置,排查是否为gzip压缩异常导致的内容丢失,确认基础上传功能正常后再按需开启压缩。
内容的提问来源于stack exchange,提问作者Thelma Ibeh
相关产品推荐
相关产品推荐

