使用Cloud Functions for Firebase和@ google-cloud / storage删除图像时出现问题

时间:2017-04-03 06:48:21

标签: node.js firebase google-cloud-platform google-cloud-storage firebase-storage

我尝试在Cloud Functions for Firebase中创建一个脚本,该脚本将对db事件做出反应并删除在其中一个参数中有路径的图像(" fullPath")。 / p>

这是我使用的代码:

'use strict';

const functions = require('firebase-functions');
const request = require('request-promise');
const admin = require('firebase-admin');
const gcs = require('@google-cloud/storage')({
    projectId: 'XXXXXXX',
    credentials: {
        // removed actual credentials from here
    }});

admin.initializeApp(functions.config().firebase);

// Deletes the user data in the Realtime Datastore when the accounts are deleted.
exports.removeImageOnNodeRemoval = functions.database
    .ref("images/{imageId}")
    .onWrite(function (event) {

        // exit if we are creating a new record (when no previous data exists)
        if (!event.data.previous.exists()) {
            console.log("a new image added");
            return;
        }

        // exit if we are just trying to update the image
        if (event.data.exists()) {
            console.log("image is been modified");
            return;
        }

        let previousData = event.data.previous.val();
        if(!previousData || !previousData.fullPath){
            console.log("no data in the previous");
            return;
        }

        let bucketName = 'XXXXXXX';
        console.log("default bucketName", gcs.bucket(bucketName));
        let file = gcs.bucket(bucketName).file(previousData.fullPath);
        console.log('the file /'+previousData.fullPath, file);

        file.exists().then(function(data) {
            let exists = data[0];
            console.info("file exists", exists);
        });

        file.delete().then(function() {
            // File deleted successfully
            console.log("image removed from project", previousData.fullPath);

        }).catch(function(error) {
            // Uh-oh, an error occurred!
            console.error("failed removing image from project", error, previousData);
        });

    });

我得到的错误:

failed removing image from project { ApiError: Not Found
    at Object.parseHttpRespBody (/user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:192:30)
    at Object.handleResp (/user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:132:18)
    at /user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:465:12
    at Request.onResponse [as _callback] (/user_code/node_modules/@google-cloud/storage/node_modules/retry-request/index.js:120:7)
    at Request.self.callback (/user_code/node_modules/@google-cloud/storage/node_modules/request/request.js:188:22)
    at emitTwo (events.js:106:13)
    at Request.emit (events.js:191:7)
    at Request.<anonymous> (/user_code/node_modules/@google-cloud/storage/node_modules/request/request.js:1171:10)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
    at IncomingMessage.<anonymous> (/user_code/node_modules/@google-cloud/storage/node_modules/request/request.js:1091:12)
    at IncomingMessage.g (events.js:291:16)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)
  code: 404,
  errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ],
  response: undefined,
  message: 'Not Found' } { contentType: 'image/png',
  fullPath: 'images/1491162408464hznsjdt6oaqtqmukrzfr.png',
  name: '1491162408464hznsjdt6oaqtqmukrzfr.png',
  size: '44.0 KB',
  timeCreated: '2017-04-02T19:46:48.855Z',
  updated: '2017-04-02T19:46:48.855Z' }

我尝试过使用和不使用凭据进行google-cloud / storage(认为他们可能会在firebase.functions中自动填充 - 我需要它们吗?)。我试过在文件的路径中添加一个斜杠。我已经验证了文件实际存在于存储桶中(即使file.exists()返回false)。我提供的凭据是针对我使用存储服务的管理员权限创建的iam。

我还在免费套餐中启用了结算帐户。

任何想法?

2 个答案:

答案 0 :(得分:7)

好的,所以我解决了这个问题。这是我的结论:

  • 您需要添加到您的存储桶名称&#34; .appspot.com&#34;。它没有写在文档中的任何地方,并且在firebase中获取您的存储桶名称对于谷歌云中不熟悉的人来说已经够难了。我希望他们能将这些小小的信息添加到他们的文档中,或者明确说明你在firebase中的名字是什么。
  • 使用环境变量 process.env.GCLOUD_PROJECT ,它应该具有与firebase中的存储桶ID相同的项目ID。再次,记得向它添加.appspot.com后缀。
  • 关于GCS的凭据,在使用firebase的云功能时,您不需要提供它们。你似乎已经过身份验证了。

答案 1 :(得分:5)

确保您的广告位名称包含gs://

EG。而不是gs://my-project-id.appspot.com使用my-project-id.appspot.com

let bucket = gcs.bucket('my-project-id.appspot.com')

如果您从例如Android代码中复制存储桶名称,可能会发生这种情况(就像我对我做的那样),您可以使用完整的URL连接存储,即。 storage.getReferenceFromUrl('gs://my-proj...

此外,用于初始化projectId的{​​{1}}变量似乎不需要gcs后缀(但如果包含它,则不应该中断) )。 IE浏览器。 appspot.com应该足够了。

最后,GCS node package docs表示您需要生成单独的JSON以作为projectId:'my-project-id'传递以在本地进行测试。好消息是 - 您可以使用Firebase Admin SDK密钥,而不是Get Started Server/Admin docs中所述。