Last active
May 14, 2018 09:25
-
-
Save steelx/13b46e7740b695d794f55f2c4e5b4ed4 to your computer and use it in GitHub Desktop.
firebase functions thumbnail
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
const mkdirp = require('mkdirp-promise'); | |
const gcs = require('@google-cloud/storage')({ keyFilename: 'service-account-key.json' }); | |
const admin = require('firebase-admin'); | |
var serviceAccount = require('./service-account-key.json'); | |
admin.initializeApp({ | |
credential: admin.credential.cert(serviceAccount), | |
databaseURL: 'https://<PROJECT_ID>.firebaseio.com' | |
}); | |
const spawn = require('child-process-promise').spawn; | |
const path = require('path'); | |
const os = require('os'); | |
const fs = require('fs'); | |
// Max height and width of the thumbnail in pixels. | |
const THUMB_MAX_HEIGHT = 640; | |
const THUMB_MAX_WIDTH = 640; | |
// Thumbnail prefix added to file names. | |
const THUMB_PREFIX = 'thumb_'; | |
/** | |
* When an image is uploaded in the Storage bucket We generate a thumbnail automatically using | |
* ImageMagick. | |
* After the thumbnail has been generated and uploaded to Cloud Storage, | |
* we write the public URL to the Firebase Realtime Database. | |
*/ | |
module.exports = (object) => { | |
const getUIDFromName = (name) => { | |
const str = name; // "users/u1xuI9dazWY3U2Ru6ljJEG3v2AD3/90342bac-5028-461d-8bc2-eb2e6b9592f7"; | |
const regex = /users\/\s*(.*?)\s*\//g; | |
const match = regex.exec(str); | |
return match[1]; | |
}; | |
// File and directory paths. | |
const filePath = object.name; | |
const UID = getUIDFromName(filePath); | |
console.log("generateThumbnail UID", UID); | |
const contentType = object.contentType; // This is the image MIME type | |
const fileDir = path.dirname(filePath); | |
const fileName = path.basename(filePath); | |
const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}`)); | |
const tempLocalFile = path.join(os.tmpdir(), filePath); | |
const tempLocalDir = path.dirname(tempLocalFile); | |
const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath); | |
// Exit if this is triggered on a file that is not an image. | |
if (!contentType.startsWith('image/')) { | |
console.log('This is not an image.'); | |
return null; | |
} | |
// Exit if the image is already a thumbnail. | |
if (fileName.startsWith(THUMB_PREFIX)) { | |
console.log('Already a Thumbnail.'); | |
return null; | |
} | |
// Cloud Storage files. | |
const bucket = gcs.bucket(object.bucket); | |
const file = bucket.file(filePath); | |
const thumbFile = bucket.file(thumbFilePath); | |
const metadata = { | |
contentType: contentType, | |
// To enable Client-side caching you can set the Cache-Control headers here. Uncomment below. | |
// 'Cache-Control': 'public,max-age=3600', | |
}; | |
// Create the temp directory where the storage file will be downloaded. | |
return mkdirp(tempLocalDir).then(() => { | |
// Download file from bucket. | |
return file.download({ destination: tempLocalFile }); | |
}).then(() => { | |
console.log('The file has been downloaded to', tempLocalFile); | |
// Generate a thumbnail using ImageMagick. | |
return spawn('convert', [tempLocalFile, '-thumbnail', `${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`, tempLocalThumbFile], { capture: ['stdout', 'stderr'] }); | |
}).then(() => { | |
console.log('Thumbnail created at', tempLocalThumbFile); | |
// Uploading the Thumbnail. | |
return bucket.upload(tempLocalThumbFile, { destination: thumbFilePath, metadata: metadata }); | |
}).then(() => { | |
console.log('Thumbnail uploaded to Storage at', thumbFilePath); | |
// Once the image has been uploaded delete the local files to free up disk space. | |
fs.unlinkSync(tempLocalFile); | |
fs.unlinkSync(tempLocalThumbFile); | |
// Get the Signed URLs for the thumbnail and original image. | |
const config = { | |
action: 'read', | |
expires: '03-01-2500', | |
}; | |
return Promise.all([ | |
thumbFile.getSignedUrl(config), | |
file.getSignedUrl(config), | |
]); | |
}).then((results) => { | |
console.log('Got Signed URLs.'); | |
const thumbResult = results[0]; | |
const originalResult = results[1]; | |
const thumbFileUrl = thumbResult[0]; | |
const fileUrl = originalResult[0]; | |
// Add the URLs to the Database | |
return admin.database().ref('users/'+ UID).set({ photo: fileUrl, thumbnail: thumbFileUrl }); | |
}).then(() => console.log('Thumbnail URLs saved to database.')); | |
}; |
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
const functions = require('firebase-functions'); | |
const generateThumbnail = require('./generateThumb'); | |
exports.generateThumbnail = functions.storage.object().onFinalize(generateThumbnail); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment