使用 Cloud Functions for Firebase 和 @google-cloud/storage 删除图像时出现问题
issues deleting an image using Cloud Functions for Firebase and @google-cloud/storage
我正在尝试在 Cloud Functions for Firebase 中创建一个脚本,该脚本将对数据库事件做出反应并删除其路径在其中一个参数 ("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() returns false)。我提供的凭据用于我创建的具有存储服务管理员权限的 iam。
我还启用了免费计划的计费帐户。
有什么想法吗?
好的,所以我解决了这个问题。这是我的结论:
- 您需要将“.appspot.com”添加到您的存储桶名称中。它没有写在文档中的任何地方,对于不熟悉 google 云的人来说,在 firebase 中获取你的存储桶名称已经够难了。我希望他们将这些信息添加到他们的文档中,或者明确说明你的 bucket 在 firebase 中的名称。
- 使用环境变量 process.env.GCLOUD_PROJECT,它应该具有与您在 firebase 中的存储桶 ID 相同的项目 ID。再次提醒,记得加上 .appspot.com 后缀。
- 关于 GCS 的凭据,在使用 firebase 的云函数时不需要提供它们。您似乎已经通过身份验证了。
确保您的存储桶名称不包括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...
.
此外,您用来初始化 gcs
的 projectId
变量似乎不需要 appspot.com
后缀(但如果包含它,它应该不会中断)。 IE。 projectId:'my-project-id'
应该足够了。
最后,GCS node package docs states you need to generate separate JSON to pass as keyFilename
to test things locally. Good news is - you can use the Firebase Admin SDK key, as described in the Get Started Server/Admin docs。
我正在尝试在 Cloud Functions for Firebase 中创建一个脚本,该脚本将对数据库事件做出反应并删除其路径在其中一个参数 ("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() returns false)。我提供的凭据用于我创建的具有存储服务管理员权限的 iam。
我还启用了免费计划的计费帐户。
有什么想法吗?
好的,所以我解决了这个问题。这是我的结论:
- 您需要将“.appspot.com”添加到您的存储桶名称中。它没有写在文档中的任何地方,对于不熟悉 google 云的人来说,在 firebase 中获取你的存储桶名称已经够难了。我希望他们将这些信息添加到他们的文档中,或者明确说明你的 bucket 在 firebase 中的名称。
- 使用环境变量 process.env.GCLOUD_PROJECT,它应该具有与您在 firebase 中的存储桶 ID 相同的项目 ID。再次提醒,记得加上 .appspot.com 后缀。
- 关于 GCS 的凭据,在使用 firebase 的云函数时不需要提供它们。您似乎已经通过身份验证了。
确保您的存储桶名称不包括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...
.
此外,您用来初始化 gcs
的 projectId
变量似乎不需要 appspot.com
后缀(但如果包含它,它应该不会中断)。 IE。 projectId:'my-project-id'
应该足够了。
最后,GCS node package docs states you need to generate separate JSON to pass as keyFilename
to test things locally. Good news is - you can use the Firebase Admin SDK key, as described in the Get Started Server/Admin docs。