Created
February 6, 2018 02:36
-
-
Save mfurlend/7aeaf19cf4d902e8b9c6368bb08fa0e6 to your computer and use it in GitHub Desktop.
#firebase #google #cloud storage #cloud functions #imagemagik
This file contains hidden or 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
const functions = require('firebase-functions'); | |
const admin = require('firebase-admin'); | |
admin.initializeApp(functions.config().firebase); | |
const gcs = require('@google-cloud/storage')(); | |
const exec = require('child-process-promise').exec; | |
const LOCAL_TMP_FOLDER = '/tmp/'; | |
/** | |
* When an image is uploaded in the Storage bucket the information and metadata of the image (the | |
* output of ImageMagick's `identify -verbose`) is saved in the Realtime Database. | |
*/ | |
exports.metadata = functions.storage.object().onChange(event => { | |
const object = event.data; | |
const filePath = object.name; | |
const fileName = filePath.split('/').pop(); | |
const tempLocalFile = `${LOCAL_TMP_FOLDER}${fileName}`; | |
// Exit if this is triggered on a file that is not an image. | |
if (!object.contentType.startsWith('image/')) { | |
console.log('This is not an image.'); | |
return; | |
} | |
// Exit if this is a move or deletion event. | |
if (object.resourceState === 'not_exists') { | |
console.log('This is a deletion event.'); | |
return; | |
} | |
// Download file from bucket. | |
const bucket = gcs.bucket(object.bucket); | |
return bucket.file(filePath).download({ | |
destination: tempLocalFile | |
}).then(() => { | |
// Get Metadata from image. | |
return exec(`identify -verbose "${tempLocalFile}"`).then(result => { | |
const metadata = imageMagickOutputToObject(result.stdout); | |
// Save metadata to realtime datastore. | |
return admin.database().ref(makeKeyFirebaseCompatible(filePath)).set(metadata).then(() => { | |
console.log('Wrote to:', filePath, 'data:', metadata); | |
}); | |
}); | |
}); | |
}); | |
/** | |
* Convert the output of ImageMagick's `identify -verbose` command to a JavaScript Object. | |
*/ | |
function imageMagickOutputToObject(output) { | |
let previousLineIndent = 0; | |
const lines = output.match(/[^\r\n]+/g); | |
lines.shift(); // Remove First line | |
lines.forEach((line, index) => { | |
const currentIdent = line.search(/\S/); | |
line = line.trim(); | |
if (line.endsWith(':')) { | |
lines[index] = makeKeyFirebaseCompatible(`"${line.replace(':', '":{')}`); | |
} else { | |
const split = line.replace('"', '\\"').split(': '); | |
split[0] = makeKeyFirebaseCompatible(split[0]); | |
lines[index] = `"${split.join('":"')}",`; | |
} | |
if (currentIdent < previousLineIndent) { | |
lines[index - 1] = lines[index - 1].substring(0, lines[index - 1].length - 1); | |
lines[index] = new Array(1 + (previousLineIndent - currentIdent) / 2).join('}') + ',' + lines[index]; | |
} | |
previousLineIndent = currentIdent; | |
}); | |
output = lines.join(''); | |
output = '{' + output.substring(0, output.length - 1) + '}'; // remove trailing comma. | |
output = JSON.parse(output); | |
console.log('Metadata extracted from image', output); | |
return output; | |
} | |
/** | |
* Makes sure the given string does not contain characters that can't be used as Firebase | |
* Realtime Database keys such as '.' and replaces them by '*'. | |
*/ | |
function makeKeyFirebaseCompatible(key) { | |
return key.replace(/\./g, '*'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment