Google Cloud Storage的WritableStream是否有文档?如何等待上传完成?
关于Google Cloud Storage WritableStream的文档与上传完成等待方案
一、WritableStream的文档说明
bucket.file(dstFile).createWriteStream()返回的其实是Node.js原生的stream.Writable对象,GCS的Node.js客户端只是基于这个原生流做了封装,用来和GCS存储服务交互,所以核心的流操作逻辑完全遵循Node.js的标准流规范,相关细节可以参考Node.js官方的Stream模块文档。
二、等待上传完成的具体实现
你遇到的问题本质是GCF异步执行特性导致的:ffmpeg处理完输出后,流可能还在后台向GCS上传数据,这时候直接返回函数会让上传过程被中断,最终导致目标文件未完全生成。下面两种方法可以帮你解决这个问题:
方法1:用Promise包裹流事件监听
把流的finish(上传完成)和error(上传出错)事件转换成Promise,配合async/await确保上传完成后再结束函数:
const { Storage } = require('@google-cloud/storage'); const storage = new Storage(); const ffmpeg = require('fluent-ffmpeg'); exports.transcodeVideo = async (req, res) => { const srcBucket = storage.bucket('你的源存储桶名称'); const dstBucket = storage.bucket('你的目标存储桶名称'); const srcFile = '源文件路径'; const dstFile = '转码后目标文件路径'; // 创建GCS写入流 const remoteWriteStream = dstBucket.file(dstFile).createWriteStream(); // 用Promise封装流的完成与错误事件 const waitForUpload = new Promise((resolve, reject) => { remoteWriteStream.on('finish', resolve); remoteWriteStream.on('error', reject); }); // 执行ffmpeg转码并将输出管道到GCS写入流 ffmpeg(srcBucket.file(srcFile).createReadStream()) .outputOptions('-vcodec', 'libx264', '-acodec', 'aac') // 示例转码参数,可按需调整 .pipe(remoteWriteStream); try { // 等待上传完成 await waitForUpload; res.status(200).send('转码并上传完成'); } catch (err) { console.error('上传失败:', err); res.status(500).send('转码上传失败'); } };
方法2:使用stream/promises的finished方法(Node.js 15+支持)
如果你的GCF运行环境Node.js版本在15及以上,可以用Node.js原生的stream/promises模块简化代码,它提供的finished方法可以直接等待流完成:
const { Storage } = require('@google-cloud/storage'); const { finished } = require('stream/promises'); const storage = new Storage(); const ffmpeg = require('fluent-ffmpeg'); exports.transcodeVideo = async (req, res) => { // ... 前面的存储桶、文件路径定义和方法1一致 const remoteWriteStream = dstBucket.file(dstFile).createWriteStream(); ffmpeg(srcBucket.file(srcFile).createReadStream()) .outputOptions('-vcodec', 'libx264', '-acodec', 'aac') .pipe(remoteWriteStream); try { // 等待流完成 await finished(remoteWriteStream); res.status(200).send('转码并上传完成'); } catch (err) { console.error('上传失败:', err); res.status(500).send('转码上传失败'); } };
注意事项
- 务必监听
error事件,避免上传出错时函数静默失败,同时未处理的错误会导致GCF异常终止。 - 如果你的GCF环境Node.js版本较低(低于15),建议用第一种方法,或者手动安装
stream-finished第三方包来替代原生的stream/promises功能。
内容的提问来源于stack exchange,提问作者GaryO
相关产品推荐
相关产品推荐

