Firebase谷歌云函数:createReadStream导致文件为空

3

我正试图通过谷歌云函数处理一个视频文件(存储在Google Firebase存储中)。我有能够将整个视频文件下载到NodeJS Google Cloud函数中的工作代码:await bucket.file(filePath).download({ destination: tempFile })

但目标仅是读取帧速率,因此视频文件的标题就足够了。但是createReadStream给我返回一个空的tempFile。非常感谢您的任何建议!

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)
})
2个回答

4
如已提到,应使用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()

1
你的问题在于流API没有被promisifed。因此,await无效,你的函数会在流被piped之前继续执行,并且当你第二次stat它时,文件仍然是零长度。 download方法运行正常,因为它返回一个Promise。 这个答案概述了你需要采取的一般方法。总的来说,你基本上希望进行piping的代码部分如下所示:
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事件发生,当管道完成并关闭流时。显然,您可能还想在错误处理程序中做一些更聪明的事情,但这是您所需的一般形式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接