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

Express调用GCS流式下载时无法捕获文件不存在错误如何解决

问题根源
  • createReadStream() 方法返回的是流对象,流运行过程中发生的错误(比如文件不存在、网络异常)是通过error事件触发的,不属于Promise异常,也不会被try/catch捕获
  • pipe() 方法返回的是目标流,本身不是Promise,await在这里没有任何实际作用,不会等待流传输完成,也不会捕获流的错误
  • 你遇到的报错是典型的流错误未被监听,Node.js遇到未处理的error事件会直接崩溃进程
修复方案

你可以通过监听流的error事件处理异常,也可以先判断文件是否存在再返回流,推荐修复代码如下:

const express = require('express')
const {Storage} = require('@google-cloud/storage');
let server = express()
const storage = new Storage();
const bucketName = '<some-bucket-name>'

server.get('/*', async (req, res) => {
  const widthString = req.query.width
  const heightString = req.query.height
  const format = req.query.format
  const fileName = req.path.substring(1);
  console.log("url: ", req.path)
  let width, height
  if (widthString) {
    width = parseInt(widthString)
  }
  if (heightString) {
    height = parseInt(heightString)
  }

  const file = storage.bucket(bucketName).file(fileName)
  // 先判断文件是否存在,提前拦截404
  const [exists] = await file.exists().catch(err => {
    console.error('检查文件存在性失败:', err)
    return [false]
  })
  
  if (!exists) {
    res.status(404).send('图片不存在')
    return
  }

  res.type(`image/${format || 'png'}`)
  const readStream = file.createReadStream()
  // 监听流错误,避免进程崩溃
  readStream.on('error', err => {
    console.error('读取文件流失败:', err)
    if (!res.headersSent) {
      res.status(500).send('读取资源失败')
    }
  })
  readStream.pipe(res)
})
额外优化建议

也可以直接使用Node.js官方提供的pipeline方法替代pipe,pipeline会自动处理流的错误、资源销毁,并且支持Promise封装,更适合异步场景:

// 顶部引入pipeline
const { pipeline } = require('stream/promises')

// 流传输部分替换为如下代码,原有try/catch可以正常捕获错误
try {
  res.type(`image/${format || 'png'}`)
  await pipeline(file.createReadStream(), res)
} catch (err) {
  console.error('流传输失败:', err)
  if (!res.headersSent) {
    res.status(err.code === 404 ? 404 : 500).send('资源访问失败')
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:45:03