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

Posted

技术标签:

【中文标题】使用 Cloud Functions for Firebase 和 @google-cloud/storage 删除图像时出现问题【英文标题】:issues deleting an image using Cloud Functions for Firebase and @google-cloud/storage 【发布时间】:2017-08-27 22:29:43 【问题描述】:

我正在尝试在 Cloud Functions for Firebase 中创建一个脚本,该脚本将对 db 事件做出反应并删除其路径位于参数之一(“fullPath”)中的图像。

这是我正在使用的代码:

'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。

我还在免费计划中启用了结算帐户。

有什么想法吗?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

确保您的存储桶名称包含gs://

例如。而不是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...

.

此外,用于初始化 gcsprojectId 变量似乎不需要 appspot.com 后缀(但如果包含它,它不应该中断)。 IE。 projectId:'my-project-id' 应该足够了。

最后,GCS node package docs 声明您需要生成单独的 JSON 以作为 keyFilename 传递以在本地进行测试。好消息是 - 您可以改用 Get Started Server/Admin docs 中所述的 Firebase Admin SDK 密钥。

【讨论】:

谢谢!这对我有用(我和你做了同样的事情,从我的前端代码中复制它),除了它 notappspot.com 部分一起工作。我刚刚做了let bucket = gcs.bucket('my-project-id') 如果我把它和appspot.com 放在一起,它会从OP的问题中抛出错误。

以上是关于使用 Cloud Functions for Firebase 和 @google-cloud/storage 删除图像时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

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

使用 Cloud Functions for Firebase 发送推送通知

使用 Cloud Functions for Firebase 时出现 CORS 错误

Cloud Functions for Firebase 组织

如何使用 Firestore 在 Cloud Functions for Firebase 中获取服务器时间戳?

Cloud Functions for Firebase 在生产中的 mongodb 错误