I'm trying to create a script in Cloud Functions for Firebase that will react to a db event and remove an image that has its path in one of the params ("fullPath").
this is the code i'm using:
'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);
});
});
the error i'm getting:
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' }
i have tried with and without credentials to google-cloud/storage (thinking they might get auto filled while im in firebase.functions - do i need them?). i have tried adding a slash to the file's path. i have validated that the file actually exists in the bucket (even tho file.exists() returns false). the credentials i provided are for an iam i created with admin privileges for the storage service.
i have also enable the billing account on the free plan.
any ideas?
ok, so i got this solved. here are my conclusions:
Make sure your bucket name doesn't include gs://
Eg. instead of gs://my-project-id.appspot.com
use my-project-id.appspot.com
let bucket = gcs.bucket('my-project-id.appspot.com')
This may happen to you (as it did to me) if you copy your bucket name from, for instance, Android code, where you can use full URL to connect with storage, ie. storage.getReferenceFromUrl('gs://my-proj...
.
Also, it seems the projectId
variable you use to initialise gcs
doesn't need the appspot.com
suffix (but it shouldn't break if you have it included). Ie. projectId:'my-project-id'
should be suffice.
Lastly, the 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 instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With