-
-
Save codediodeio/d4cdcfc16f02d369d6943471727c6062 to your computer and use it in GitHub Desktop.
| const functions = require('firebase-functions'); | |
| const gcs = require('@google-cloud/storage')(); | |
| const sharp = require('sharp') | |
| const _ = require('lodash'); | |
| const path = require('path'); | |
| const os = require('os'); | |
| exports.generateThumbnail = functions.storage.object('uploads/{imageId}').onChange(event => { | |
| const object = event.data; // The Storage object. | |
| console.log(object) | |
| const fileBucket = object.bucket; // The Storage bucket that contains the file. | |
| const filePath = object.name; // File path in the bucket. | |
| const contentType = object.contentType; // File content type. | |
| const resourceState = object.resourceState; // The resourceState is 'exists' or 'not_exists' (for file/folder deletions). | |
| const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1. | |
| const SIZES = [64, 256, 512]; // Resize target width in pixels | |
| if (!contentType.startsWith('image/') || resourceState == 'not_exists') { | |
| console.log('This is not an image.'); | |
| return; | |
| } | |
| if (_.includes(filePath, '_thumb')) { | |
| console.log('already processed image'); | |
| return; | |
| } | |
| const fileName = filePath.split('/').pop(); | |
| const bucket = gcs.bucket(fileBucket); | |
| const tempFilePath = path.join(os.tmpdir(), fileName); | |
| return bucket.file(filePath).download({ | |
| destination: tempFilePath | |
| }).then(() => { | |
| _.each(SIZES, (size) => { | |
| let newFileName = `${fileName}_${size}_thumb.png` | |
| let newFileTemp = path.join(os.tmpdir(), newFileName); | |
| let newFilePath = `thumbs/${newFileName}` | |
| sharp(tempFilePath) | |
| .resize(size, null) | |
| .toFile(newFileTemp, (err, info) => { | |
| bucket.upload(newFileTemp, { | |
| destination: newFilePath | |
| }); | |
| }); | |
| }) | |
| }) | |
| }) |
| { | |
| "name": "functions", | |
| "description": "Cloud Functions for Firebase", | |
| "dependencies": { | |
| "@google-cloud/storage": "^0.4.0", | |
| "firebase-admin": "^4.1.2", | |
| "firebase-functions": "^0.5", | |
| "lodash": "^4.17.4", | |
| "request-promise": "^2.0.0", | |
| "sharp": "^0.18.1" | |
| }, | |
| "private": true | |
| } |
I'm trying to use your example but to generate thumbnails inside Firebase Storage. I am not restricting to the uploads/ folder as I want it in different folder ({user}/avatar/{imageId}) in my case. I am getting an error in the Firebase functions log ApiError: Forbidden at new util.ApiError (/user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:107:10)
Do I have to add a certificate as mentioned here?
cloud function with sharp , it takes around 8-10 seconds to generate a single thumbnail from a single image file . tell me this is normal .
onChange() is now deprecated. you should change it to onFinalize()
cloud function with sharp , it takes around 8-10 seconds to generate a single thumbnail from a single image file . tell me this is normal .
I'm having the same issue.
TypeError: gcs.bucket is not a function
at exports.generateThumbnail.functions.storage.object.onFinalize (/user_code/index.js:33:22)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:105:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:135:20)
at /var/tmp/worker/worker.js:769:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
UPDATE 2020:
This still works, you have to change some code:
1 . Change
const gcs = require('@google-cloud/storage')();to
const { Storage } = require('@google-cloud/storage');
const gcs = new Storage()-
onChange()is now deprecated. Change it toonFinalize(). -
If you are using
"fs-extra": "^9.0.0", downgrade it to version8.1.0. Why?v9.0.0requires node version >=10it seems, whereas cloud functions are still stable only for nodev8.
thank you very much... this is a great example! very useful