Cloud Run(Node.js)下载GCS对象遇‘cannot read property of null’错误求助
Cloud Run(Node.js)中GCS对象流式写入/tmp失败,但内存缓存写入正常
我在运行Node.js的Google Cloud Run服务里,尝试把Google Cloud Storage(GCS)的对象下载到/tmp目录,按照官方教程写了如下代码:
exports.resizeImage = async (eventData) => { const file = storage.bucket(eventData.bucket).file(eventData.name); // 解析图片扩展名 const [metadata] = await file.getMetadata(); const extension = metadataContentTypeToExtension(metadata.contentType); const tempLocalPath = `/tmp/${path.parse(file.name).base}.${extension}`; console.log(tempLocalPath); // 输出 "/tmp/clpeytui4003nfcsjqjyifk0d.jpg" try { // 测试是否正确定位到对象 const url = await file.getSignedUrl({ action: 'read', expires: '03-17-2025', }); console.log(`访问URL: ${url}`); } catch (err) { console.error('无法获取预签名URL:'); console.error(err); } // 从存储桶下载文件 try { console.log(`正在下载 ${file.name} 到 ${tempLocalPath}...`); const dlPromise = file.download({ destination: tempLocalPath }); dlPromise.catch((err) => { console.error('下载失败(Promise捕获).'); console.error(err); }); } catch (err) { console.error(`文件下载失败: ${err}`); return; } }
Cloud Run日志里出现错误:Error: read ECONNRESET,报错位置在底层的stream-shift调用中。
预签名URL可以在浏览器正常访问,说明文件定位没问题,而且已经给服务分配了storage.admin权限。我猜测是获取下载数据流时出了问题,于是尝试自定义下载函数:
const downloadFile = (file, downloadPath) => new Promise((resolve, reject) => { console.log('尝试下载文件...'); file .createReadStream() .pipe(fs.createWriteStream(downloadPath)) .on('finish', () => { console.log(`图片已下载到本地路径 ${downloadPath}`); console.log(`文件大小: ${fs.statSync(downloadPath).size} 字节`); resolve(); }) .on('error', (err) => { console.error('文件下载失败.', err); reject(err); }); });
但还是出现同样的底层stream-shift错误,而且自定义的错误日志根本没触发。
11/26更新:我把.pipe(fs.createWriteStream(downloadPath))替换成自己实现的内存缓存数据方式后,问题解决了:
const downloadFile = (file, downloadPath) => new Promise((resolve, reject) => { const buffer = []; file .createReadStream() // .pipe(fs.createWriteStream(downloadPath)) // 有问题的代码行 .on('data', (chunk) => { buffer.push(chunk); }) .on('finish', () => { fs.writeFileSync(downloadPath, Buffer.concat(buffer)); resolve(); }) .on('error', (err) => { console.error('文件下载失败.', err); reject(err); }); });
(已验证下载的文件和原文件完全一致)
问题显然出在流式写入而非缓存写入的方式上,我搞不懂为什么官方教程提供的代码没法正确处理流式写入,求解决方案。
内容的提问来源于stack exchange,提问作者mightimaus
相关产品推荐
相关产品推荐

