将文件从 Firebase Cloud Functions 上传到云存储

问题描述 投票:0回答:5

文档太复杂了,我无法理解。它演示了如何将文件从 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?我应该使用
firebase-admin
而不是
@google-cloud/storage
吗?为什么这不起作用:

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-promise
path
os
fs
;没有修复丢失的
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
├── [email protected]
├── 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
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

换句话说,

firebase-admin
Node 6.11.2
有问题。我应该使用节点版本管理器恢复到旧版本的节点吗?

firebase google-cloud-functions firebase-storage
5个回答
13
投票
  1. 前往 https://console.cloud.google.com/iam-admin/iam
  2. 单击您的
    App Engine default service account
  3. 旁边的铅笔图标
  4. + ADD ANOTHER ROLE
  5. 添加
    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. 转到服务帐户并生成私钥
  2. 将 JSON 文件放入函数文件夹中(位于 src 和 node_modules 旁边)
  3. 进入存储并复制不包含前面“gs://”的URL。初始化 admin 时,将其用作存储桶 url。
  4. 使用上面您的项目 ID 作为数据库 URL。

6
投票

参见管理云存储简介 API 进一步了解 有关如何在 Firebase Admin SDK 中使用云存储服务的详细信息。

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.

关于上传对象,请参见云存储文档上传对象示例代码:

// 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}.`);

3
投票

我通过 Google Cloud Functions 将文件从硬盘上传到 Firebase Cloud Storage。首先,我找到了 Google Cloud Functions 的文档bucket.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 样板。

其余代码在我的计算机硬盘驱动器上的项目目录的

hello_world.ogg
文件夹中找到文件
functions
并将其上传到目录
Test_Folder
并在我的 Firebase 中将该文件的名称更改为
hello_world.dog
云储存。这会返回一个承诺,并且下一行
const file = data[0];
是不必要的,除非您想对文件执行其他操作。

最后我们

return 0;
。该行除了防止出现错误消息之外什么也不做

Function returned undefined, expected Promise or Value

0
投票

对于来到这里的人们,想知道为什么他们在本地调试时没有收到错误,但文件没有出现在在线控制台中。

解决方案:不要在本地启动存储模拟器。

即,当您只想调试功能时:

firebase emulators:start --inspect-functions --only functions


-1
投票
if (req.rawBody) {
    busboy.end(req.rawBody);
}
else {
    req.pipe(busboy);
}

如本期所述:https://github.com/GoogleCloudPlatform/cloud-functions-emulator/issues/161#issuecomment-376563784

© www.soinside.com 2019 - 2024. All rights reserved.