【问题标题】:Firebase Google Cloud Function: createReadStream results in empty fileFirebase Google Cloud 函数:createReadStream 结果为空文件
【发布时间】:2020-03-27 08:06:15
【问题描述】:

我尝试通过 Google Cloud Function 处理视频文件(存储在 Google Firebase 存储中)。我有将整个视频文件下载到 NodeJS Google 云函数中的工作代码:await bucket.file(filePath).download({ destination: tempFile })。 但目标只是读取帧速率,因此视频文件的标题就足够了。但是createReadStream 给了我一个空的临时文件。任何建议都非常感谢!

exports.checkFramerate = functions.region('europe-west1').storage.object().onFinalize(async (object, context) => {
    const bucket =  admin.storage().bucket(object.bucket); // Bucket class
    const filePath = object.name;   //  videos/xbEXdMNFb1Blbd9r2E8m/comp_test.mp4
    const fileName = filePath.split('/').pop(); // comp_test.mp4
    const bucketDir = path.dirname(filePath); // videos/xbEXdMNFb1Blbd9r2E8m

    const tempFile = path.join(os.tmpdir(), 'temp.mp4')
    fs.closeSync(fs.openSync(tempFile, 'w'))
    console.log("tempFile size1", fs.statSync(tempFile).size)

    // await bucket.file(filePath).download({ destination: tempFile }); // this works: tempFile size2 = 3180152
    await bucket.file(filePath).createReadStream({                      // this does not work: tempFile size2 = 0
        start: 10000,
        end: 20000
      })
      .on('error', function(err) {console.log(err)})
      .pipe(fs.createWriteStream(tempFile));


    console.log("tempFile size2", fs.statSync(tempFile).size)

    mi(tempFile).then(data => {
        console.log("frameRate", data[0].general.frame_rate[0])
        return data[0].general.frame_rate[0];
    }).catch(e => {console.error(e)});
});

我什至尝试实现https://googleapis.dev/nodejs/storage/latest/File.html#createReadStream 的示例,但无济于事。 remoteFile.download 效果很好,但 remoteFile.createReadStream 给了我空文件...

const remoteFile = bucket.file(filePath);
const localFilename = tempFile;

remoteFile.createReadStream()
    .on('error', function(err) {})
    .on('response', function(response) {})
    .on('end', function() {})
    .pipe(fs.createWriteStream(localFilename));

fs.stat(localFilename, (err, stats) => {
    if (err) {console.log(err)}
    return console.log("stats async",stats.size)
})

【问题讨论】:

    标签: javascript node.js google-cloud-functions google-cloud-storage


    【解决方案1】:

    如前所述,应该使用 promise

    读取json文件示例

     let  buf = '';
    
     const loadData = async () => {
      return await new Promise((resolve, reject) => {
        storage.bucket('bucket-name').file('test-config.json')
          .createReadStream()
          .on('error', reject)
          .on('data', function(d) {
            buf += d;
          }).on('end', function() {
            resolve(buf)
          });
      })
    }
    
    const data = await loadData()
    

    【讨论】:

      【解决方案2】:

      您的问题是流 API 没有被承诺。因此,await 什么都不做,并且您的函数在流传输之前继续执行,并且当您第二次统计它时,该文件仍然是零长度。

      download 方法工作得很好,因为它返回一个 Promise。

      This answer 概述了您需要采取的一般方法。总之,您基本上希望执行管道的代码部分如下所示:

      const stream = bucket.file(filePath).createReadStream({
          start: 10000,
          end: 20000
        })
        .pipe(fs.createWriteStream(tempFile));
      
      await new Promise((resolve, reject) => {
          stream.on('finish', resolve);
          stream.on('error', reject);
        });
      
      console.log("tempFile size2", fs.statSync(tempFile).size)
      

      然后,您的函数将等到管道完成并关闭流时发生finish 事件。显然,您可能还想对错误处理程序做一些更聪明的事情,但这是您需要的一般形式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-22
        • 1970-01-01
        • 2021-06-02
        • 2020-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多