将文件从Firebase Cloud Functions上传到Cloud Storage

时间:2018-11-04 18:22:44

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

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?我应该使用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-promisepathosfs;没有一个可以解决丢失的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出问题了。我应该使用节点版本管理器还原到旧版本的节点吗?

3 个答案:

答案 0 :(得分:1)

我通过Google Cloud Functions将文件从硬盘驱动器上传到Firebase Cloud Storage。首先,我找到了documentation的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 Cloud Storage中的hello_world.dog。这将返回一个承诺,并且除非您要对该文件执行其他操作,否则不需要下一行const file = data[0];

最后,我们return 0;。该行除了防止出现错误消息外没有任何作用

Function returned undefined, expected Promise or Value

答案 1 :(得分:0)

  

有关更多信息,请参见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}.`);

答案 2 :(得分:0)

  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字符串解码为字节数组,然后使用该字符串保存图像。

    import * as functions from 'firebase-functions';
    import * as admin from 'firebase-admin';    
    admin.initializeApp()

    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`);

        return file.save(imageByteArray)
        .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        
    })