Created
November 1, 2017 10:44
-
-
Save ozasadnyy/f1bc84eebe5335af4618955f77dc7d5c to your computer and use it in GitHub Desktop.
Optimize images with Firebase Storage and Functions on a fly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const functions = require('firebase-functions'); | |
const gcs = require('@google-cloud/storage')(); | |
const spawn = require('child-process-promise').spawn; | |
const mkdirp = require('mkdirp-promise'); | |
const path = require('path'); | |
const os = require('os'); | |
const fs = require('fs'); | |
exports.optimizeImages = functions.storage.object().onChange(({ data }) => { | |
// File and directory paths. | |
const filePath = data.name; | |
const tempLocalFile = path.join(os.tmpdir(), filePath); | |
const tempLocalDir = path.dirname(tempLocalFile); | |
// Exit if this is triggered on a file that is not an image. | |
if (!data.contentType.startsWith('image/')) { | |
console.log('This is not an image.'); | |
return null; | |
} | |
// Exit if this is a move or deletion event. | |
if (data.resourceState === 'not_exists') { | |
console.log('This is a deletion event.'); | |
return null; | |
} | |
// Exit if file exists but is not new and is only being triggered | |
// because of a metadata change. | |
if (data.resourceState === 'exists' && data.metageneration > 1) { | |
console.log('This is a metadata change event.'); | |
return null; | |
} | |
// Cloud Storage files. | |
const bucket = gcs.bucket(data.bucket); | |
const file = bucket.file(filePath); | |
return file.getMetadata() | |
.then(([metadata]) => { | |
if (metadata.metadata && metadata.metadata.optimized) { | |
return Promise.reject('Image has been already optimized'); | |
} | |
return Promise.resolve(); | |
}) | |
.then(() => mkdirp(tempLocalDir)) | |
.then(() => file.download({ destination: tempLocalFile })) | |
.then(() => { | |
console.log('The file has been downloaded to', tempLocalFile); | |
// Generate a thumbnail using ImageMagick. | |
return spawn('convert', [tempLocalFile, '-strip', '-interlace', 'Plane', '-quality', '82', tempLocalFile]); | |
}) | |
.then(() => { | |
console.log('Optimized image created at', tempLocalFile); | |
// Uploading the Optimized image. | |
return bucket.upload(tempLocalFile, { | |
destination: file, | |
metadata: { | |
metadata: { | |
optimized: true | |
} | |
} | |
}); | |
}) | |
.then(() => { | |
console.log('Optimized image uploaded to Storage at', file); | |
// Once the image has been uploaded delete the local files to free up disk space. | |
fs.unlinkSync(tempLocalFile); | |
// Get the Signed URLs for optimized image. | |
const config = { | |
action: 'read', | |
expires: '03-01-2500' | |
}; | |
return file.getSignedUrl(config); | |
}); | |
}); |
Hello I have an error. const gcs = require('@google-cloud/storage')(); TypeError: require(...) is not a function
Try this
const {Storage} = require('@google-cloud/storage'); const gcs = new Storage();
I have wrote some different function
view here https://gist.github.com/androidovshchik/9e9c8299d393a28f74e17cf09d06d466
- Written in typescript
- Removed deprecated functions. E.g.
functions.storage.object().onChange
anddata.resourceState
are not existing now - Fixes metadata issue. Now when uploading old metadata is not erasing
- Have better optimize arguments fo ImageMagick command
- More safe execution
And it really works for today
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have an error Cannot find module '@google-cloud/storage', but i install the module via npm:
npm install --save @google-cloud/storage
Function load error: Code in file index.js can't be loaded.
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module '@google-cloud/storage'
at Function.Module._resolveFilename (module.js:476:15)
at Function.Module._load (module.js:424:25)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
at Object. (/user_code/index.js:3:45)
at Module._compile (module.js:577:32)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)