简体   繁体   English

从 Firebase Cloud Function 在 Google Cloud Bucket 中创建文件

[英]Create File in Google Cloud Bucket from Firebase Cloud Function

I have a function that monitors a node in a Realtime database and once a new child is written to the node the function simply needs to create a html document in a Google Cloud bucket.我有一个 function 监控实时数据库中的节点,一旦将新子节点写入该节点,function 只需要在 Google 云存储桶中创建 html 文档。 The HTML document will have a unique name and will contain some data from the node. HTML 文档将具有唯一名称,并将包含来自节点的一些数据。 It's all fairly straightforward, however I can't actually create and write to the document.这一切都相当简单,但是我实际上无法创建和写入文档。 I've tried 3 methods so far (outlined in the code below), none of these methods work.到目前为止,我已经尝试了 3 种方法(在下面的代码中概述),这些方法都不起作用。

const {Storage} = require('@google-cloud/storage');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const fs = require('fs');
const {StringStream} = require('@rauschma/stringio')

const instanceId = 'my-project-12345';
const bucketName = 'my-bucket';

exports.processCertification = functions.database.instance(instanceId).ref('/t/{userId}/{testId}')
    .onCreate((snapshot, context) => {
      const dataJ = snapshot.toJSON();

      var testResult = "Invalid";
      if(dataJ.r == 1) {testResult = "Positive";}
      else if(dataJ.r == 2) {testResult = "Negative";}

      console.log('Processing certificate:', context.params.testId, testResult);

      var storage = new Storage({projectId: instanceId});
      const fileName = context.params.testId + '.html';
      const fileContents = "<html><head></head><body>Result: " + testResult + "</body></html>"
      const options = {resumable:false, metadata:{contentType:'text/html'}};

      const bucket = storage.bucket(bucketName);
      const file = bucket.file(fileName);

      console.log('Saving to:' + bucketName + '/' + fileName);

      if(false) {
        // Test 1. the file.save method
        // Errors with:
        //  (node:2) MetadataLookupWarning: received unexpected error = URL is not defined code = UNKNOWN
        file.save(fileContents, options, function(err) {
          if (!err) {console.log("Save created object at " + bucketName + "/" + fileName);}
          else {console.log("Save Failed " + err);}
        });

      } else if(true) {
        // Test 2. the readStream.pipe method
        // No errors, doesn't output error message, doesn't output finish message, no file created
        fs.createReadStream(fileContents)
          .pipe(file.createWriteStream(options))
          .on('error', function(err) {console.log('WriteStream Error');})
          .on('finish', function() {console.log('WriteStream Written');});

      } else {
        // Test 3. the StringStream with readStream.pipe method
        // Errors with:
        //   (node:2) MetadataLookupWarning: received unexpected error = URL is not defined code = UNKNOWN
        const writeStream = storage.bucket(bucketName).file(fileName).createWriteStream(options);
        writeStream.on('finish', function(){console.log('WriteStream Written');}).on('error', function(err){console.log('WriteStream Error');});
        const readStream = new StringStream(fileContents);
        readStream.pipe(writeStream);

      }
      console.log('Function Finished');

      return 0;
    });

In all cases the "Processing certificate" and "Saving to" outputs appear, I also get the "Function Finished" message every time.在所有情况下,都会出现“处理证书”和“保存到”输出,我每次也会收到“功能完成”消息。 The errors (or in one case no response) is written against each of the tests in the code.错误(或者在一种情况下没有响应)是针对代码中的每个测试编写的。

My next step will be to create the file locally and then use upload() method, however each of these methods seem like they should work, plus the only error message I have is talking about URL errors so I suspect trying to use upload() method would run into the same problems as well.我的下一步将是在本地创建文件,然后使用 upload() 方法,但是这些方法中的每一个似乎都应该工作,加上我唯一的错误消息是谈论 URL 错误所以我怀疑尝试使用 upload()方法也会遇到同样的问题。

I'm using Node.JS v8.17.0 and the following packages我正在使用 Node.JS v8.17.0 和以下包

"dependencies": {
  "@google-cloud/storage": "^5.0.0",
  "@rauschma/stringio": "^1.4.0",
  "firebase-admin": "^8.10.0",
  "firebase-functions": "^3.6.1"
}

Any advice is most welcome任何建议都是最受欢迎的

In each case, you are not working with promises correctly.在每种情况下,您都没有正确使用 Promise。 For database triggers (and all other background triggers), you must return a promise that resolves when all of the asynchronous work is complete in a function.对于数据库触发器(和所有其他后台触发器),您必须 返回一个 promise,当 function 中的所有异步工作完成时,它会解析。 Right now, you're not doing anything at all with promises, while each of the APIs you're calling are all asynchronous.现在,您根本没有对 Promise 做任何事情,而您调用的每个 API 都是异步的。 Your function is just returning 0 immediately without waiting for the upload to complete, and Cloud Functions is simply terminating and cleaning up before anything can happen.您的 function 只是立即返回 0 而无需等待上传完成,而 Cloud Functions 只是在任何事情发生之前终止和清理。

I suggest choosing one of the methods that returns a promise with the upload is complete (probably file.save() ), then return that promise from the function.我建议选择一种在上传完成时返回 promise 的方法(可能是file.save() ),然后从 function 中返回 promise。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM