【问题标题】:Uploading files from Firebase Cloud Functions to Cloud Storage将文件从 Firebase Cloud Functions 上传到 Cloud Storage
【发布时间】:2019-04-08 04:43:49
【问题描述】:

documentation 太复杂了,我无法理解。它展示了如何将文件从 Cloud Storage 下载到 Cloud Functions、操作文件,然后将新文件上传到 Cloud Storage。我只想查看将文件从 Cloud Functions 上传到 Cloud Storage 的基本、最低限度的说明。为什么这不起作用:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp();

exports.storage = functions.firestore.document('Test_Value').onUpdate((change, context) => {

  var metadata = {
    contentType: 'text',
  };

  admin.storage().ref().put( {'test': 'test'}, metadata)
  .then(function() {
    console.log("Document written.");
  })
  .catch(function(error) {
    console.error(error);
  })

});

错误消息是admin.storage(...).ref is not a function。我猜firebase-admin 包括 Firestore 但不包括 Storage?我应该使用@google-cloud/storage 而不是firebase-admin?为什么这不起作用:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

const {Storage} = require('@google-cloud/storage')();
const storage = new Storage();

admin.initializeApp();

exports.storage = functions.firestore.document('Test_Value').onUpdate((change, context) => {

  storage.bucket().upload( {'test': 'test'} , {
    metadata: {
      contentType: 'text'
    }
  })

});

我什至无法部署此代码,错误消息是

Error parsing triggers: Cannot find module './clone.js'

显然缺少一个 npm 模块依赖项?但是模块不叫clone.js?我尝试要求child-process-promisepathosfs; none 修复了缺少的 clone.js 错误。

为什么admin.initializeApp(); 缺少参数,而我的index.html 文件中有:

firebase.initializeApp({
    apiKey: 'swordfish',
    authDomain: 'myapp.firebaseapp.com',
    databaseURL: "https://myapp.firebaseio.com",
    projectId: 'myapp',
    storageBucket: "myapp.appspot.com"
  });

我看到的另一个问题:

npm list -g --depth=0       

/Users/TDK/.nvm/versions/node/v6.11.2/lib
├── child_process@1.0.2
├── UNMET PEER DEPENDENCY  error: ENOENT: no such file or directory, open '/Users/TDK/.nvm/versions/node/v6.11.2/lib/node_modules/firebase-admin/package.json
├── firebase-functions@2.1.0
├── firebase-tools@6.0.1
├── firestore-backup-restore@1.3.1
├── fs@0.0.2
├── npm@6.4.1
├── npm-check@5.9.0
├── protractor@5.4.1
├── request@2.88.0
└── watson-developer-cloud@3.13.0

换句话说,firebase-adminNode 6.11.2 有问题。我应该使用 Node 版本管理器恢复到旧版本的 Node 吗?

【问题讨论】:

标签: firebase google-cloud-functions firebase-storage


【解决方案1】:
  1. 转到https://console.cloud.google.com/iam-admin/iam
  2. 单击您的App Engine default service account 旁边的铅笔图标
  3. + ADD ANOTHER ROLE
  4. 添加Cloud Functions Service Agent

在我的特定用例中,我需要将 base64 字符串解码为字节数组,然后使用它来保存图像。

    var serviceAccount = require("./../serviceAccountKey.json");

    import * as functions from 'firebase-functions';
    import * as admin from 'firebase-admin';    

    admin.initializeApp({
        projectId: serviceAccount.project_id, 
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://your_project_id_here.firebaseio.com", //update this
        storageBucket: "your_bucket_name_here.appspot.com" //update this
      });

    function uploadProfileImage(imageBytes64Str: string): Promise<any> {

        const bucket = admin.storage().bucket()
        const imageBuffer = Buffer.from(imageBytes64Str, 'base64')
        const imageByteArray = new Uint8Array(imageBuffer);
        const file = bucket.file(`images/profile_photo.png`);
        const options = { resumable: false, metadata: { contentType: "image/jpg" } }

        //options may not be necessary
        return file.save(imageByteArray, options)
        .then(stuff => {
            return file.getSignedUrl({
                action: 'read',
                expires: '03-09-2500'
              })
        })
        .then(urls => {
            const url = urls[0];
            console.log(`Image url = ${url}`)
            return url
        })
        .catch(err => {
            console.log(`Unable to upload image ${err}`)
        })
    }

然后你可以像这样调用方法并链接调用。

    uploadProfileImage(image_bytes_here)
    .then(url => {
        //Do stuff with the url here        
    })

注意:您必须使用服务帐户初始化 admin 并指定默认存储桶。 如果您只是使用admin.initializeApp(),那么您的图片网址将在 10 天后过期。

正确使用服务帐号的步骤。

  1. 转到Service Accounts 并生成私钥
  2. 将 JSON 文件放入您的函数文件夹中(在 src 和 node_modules 旁边)
  3. 转到Storage 并复制不包括前面“gs://”的URL。初始化 admin 时将其用于存储桶 url。
  4. 使用上面的项目 ID 作为数据库 URL。

【讨论】:

    【解决方案2】:

    我通过 Google Cloud Functions 将文件从我的硬盘上传到 Firebase Cloud Storage。首先,我找到了 Google Cloud Functions 的 documentationbucket.upload

    const functions = require('firebase-functions');
    const admin = require('firebase-admin');
    admin.initializeApp();
    
    exports.Storage = functions.firestore.document('Storage_Value').onUpdate((change, context) => {
    
      const {Storage} = require('@google-cloud/storage');
      const storage = new Storage();
      const bucket = storage.bucket('myapp.appspot.com');
    
      const options = {
        destination: 'Test_Folder/hello_world.dog'
      };
    
      bucket.upload('hello_world.ogg', options).then(function(data) {
        const file = data[0];
      });
    
      return 0;
    });
    

    前三行是 Cloud Functions 样板。下一行

    exports.Storage = functions.firestore.document('Storage_Value').onUpdate((change, context) => {
    

    创建云函数并设置触发器。接下来的三行更多的是 Google Cloud 样板。

    剩下的代码在我的项目目录的functions文件夹下找到我电脑硬盘上的hello_world.ogg文件,并上传到目录Test_Folder,并将文件名改成hello_world.dog in我的 Firebase 云存储。这将返回一个承诺,除非您想对该文件执行其他操作,否则下一行 const file = data[0]; 是不必要的。

    最后我们return 0;。此行除了防止错误消息外什么都不做

    Function returned undefined, expected Promise or Value
    

    【讨论】:

      【解决方案3】:

      请参阅Introduction to the Admin Cloud Storage API 了解更多信息 详细了解如何在 Firebase Admin SDK 中使用 Cloud Storage 服务。

      var admin = require("firebase-admin");
      
      var serviceAccount = require("path/to/serviceAccountKey.json");
      
      admin.initializeApp({
          credential: admin.credential.cert(serviceAccount),
          storageBucket: "<BUCKET_NAME>.appspot.com"
      });
      
      var bucket = admin.storage().bucket();
      
      // 'bucket' is an object defined in the @google-cloud/storage library.
      // See https://googlecloudplatform.github.io/google-cloud-node/#/docs/storage/latest/storage/bucket
      // for more details.
      

      关于上传对象,见Cloud Storage Documentation Uploading Objects示例代码:

      // Imports the Google Cloud client library
      const {Storage} = require('@google-cloud/storage');
      
      // Creates a client
      const storage = new Storage();
      
      /**
       * TODO(developer): Uncomment the following lines before running the sample.
       */
      // const bucketName = 'Name of a bucket, e.g. my-bucket';
      // const filename = 'Local file to upload, e.g. ./local/path/to/file.txt';
      
      // Uploads a local file to the bucket
      await storage.bucket(bucketName).upload(filename, {
        // Support for HTTP requests made with `Accept-Encoding: gzip`
        gzip: true,
        metadata: {
          // Enable long-lived HTTP caching headers
          // Use only if the contents of the file will never change
          // (If the contents will change, use cacheControl: 'no-cache')
          cacheControl: 'public, max-age=31536000',
        },
      });
      
      console.log(`${filename} uploaded to ${bucketName}.`);
      

      【讨论】:

      • 该代码创建了一个存储桶,但没有将文件上传到存储。
      • 对于第二个代码块,将字段/值 destination : 'test/coffeeLogo.png' 添加到 .upload() 选项 JSON 完成文件上传 - stackoverflow.com/a/54227249,并在此线程中 @987654324 @
      猜你喜欢
      • 2021-07-30
      • 2021-03-19
      • 2018-04-22
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-04
      相关资源
      最近更新 更多