Created
February 21, 2018 22:12
-
-
Save mflisikowski/621b05e18900e1a81e7413a64f4e118d to your computer and use it in GitHub Desktop.
Firebase Cloud Functions: Storage Thumbnails
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 mkdirp = require('mkdirp-promise') | |
const gcs = require('@google-cloud/storage')({ | |
keyFilename: '***********************************-c3d9469093.json' | |
}) | |
const admin = require('firebase-admin') | |
const spawn = require('child-process-promise').spawn | |
const path = require('path') | |
const os = require('os') | |
const fs = require('fs') | |
admin.initializeApp(functions.config().firebase) | |
const THUMB_1200_WIDTH = 1200 | |
const THUMB_600_HEIGHT = 600 | |
const THUMB_600_WIDTH = 600 | |
const THUMB_400_HEIGHT = 400 | |
const THUMB_200_WIDTH = 200 | |
const THUMB_200_HEIGHT = 200 | |
const THUMB_LARGE_PREFIX = 'thumb_large_' | |
const THUMB_SMALL_PREFIX = 'thumb_small_' | |
const THUMB_ICON_PREFIX = 'thumb_icon_' | |
exports.storageThumbnails2 = functions.storage.object() | |
.onChange((event) => { | |
const filePath = event.data.name | |
const contentType = event.data.contentType | |
const fileDir = path.dirname(filePath) | |
const fileName = path.basename(filePath) | |
const thumbLargePath = path.normalize(path.join(fileDir, `${THUMB_LARGE_PREFIX}${fileName}`)) | |
const thumbSmallPath = path.normalize(path.join(fileDir, `${THUMB_SMALL_PREFIX}${fileName}`)) | |
const thumbIconPath = path.normalize(path.join(fileDir, `${THUMB_ICON_PREFIX}${fileName}`)) | |
const tempLocalFile = path.join(os.tmpdir(), filePath) | |
const tempLocalDir = path.dirname(tempLocalFile) | |
const tempLocalThumbLarge = path.join(os.tmpdir(), thumbLargePath) | |
const tempLocalThumbSmall = path.join(os.tmpdir(), thumbSmallPath) | |
const tempLocalThumbIcon = path.join(os.tmpdir(), thumbIconPath) | |
// Exit if this is a move or deletion event. | |
if (event.data.resourceState === 'not_exists') { | |
console.log('This is a deletion event.') | |
return null | |
} | |
// 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_LARGE_PREFIX) || | |
fileName.startsWith(THUMB_SMALL_PREFIX) || | |
fileName.startsWith(THUMB_ICON_PREFIX)) { | |
console.log('Already created!') | |
return null | |
} | |
// Cloud Storage files. | |
const bucket = gcs.bucket(event.data.bucket) | |
const file = bucket.file(filePath) | |
const thumbLargeFile = bucket.file(thumbLargePath) | |
const thumbSmallFile = bucket.file(thumbSmallPath) | |
const thumbIconFile = bucket.file(thumbIconPath) | |
const metadata = { | |
contentType: contentType | |
} | |
return mkdirp(tempLocalDir) | |
.then(() => file.download({ destination: tempLocalFile })) | |
// Large thumb | |
.then(() => { console.log('The file has been downloaded to', tempLocalFile) | |
return spawn( | |
`convert`, [ | |
`-define`, | |
`jpeg:size=${THUMB_1200_WIDTH}x${THUMB_600_HEIGHT}>`, | |
tempLocalFile, | |
`-thumbnail`, | |
`${THUMB_1200_WIDTH}x${THUMB_600_HEIGHT}>^`, | |
`-gravity`, | |
`center`, | |
`-extent`, | |
`${THUMB_1200_WIDTH}x${THUMB_600_HEIGHT}>`, | |
tempLocalThumbLarge | |
] | |
) | |
}) | |
.then(() => { console.log('Thumbnail created at', tempLocalThumbLarge) | |
// Uploading the Thumbnail. | |
return bucket.upload(tempLocalThumbLarge, { | |
destination: thumbLargePath, | |
metadata: metadata | |
}) | |
}) | |
// Small thumb | |
.then(() => { console.log('The file has been downloaded to', tempLocalFile) | |
return spawn( | |
`convert`, [ | |
`-define`, | |
`jpeg:size=${THUMB_600_WIDTH}x${THUMB_400_HEIGHT}>`, | |
tempLocalFile, | |
`-thumbnail`, | |
`${THUMB_600_WIDTH}x${THUMB_400_HEIGHT}>^`, | |
`-gravity`, | |
`center`, | |
`-extent`, | |
`${THUMB_600_WIDTH}x${THUMB_400_HEIGHT}>`, | |
tempLocalThumbSmall | |
] | |
) | |
}) | |
.then(() => { console.log('Thumbnail created at', tempLocalThumbSmall) | |
// Uploading the Thumbnail. | |
return bucket.upload(tempLocalThumbSmall, { | |
destination: thumbSmallPath, | |
metadata: metadata | |
}) | |
}) | |
// Icon thumb | |
.then(() => { console.log('The file has been downloaded to', tempLocalFile) | |
return spawn( | |
`convert`, [ | |
`-define`, | |
`jpeg:size=${THUMB_200_WIDTH}x${THUMB_200_HEIGHT}>`, | |
tempLocalFile, | |
`-thumbnail`, | |
`${THUMB_200_WIDTH}x${THUMB_200_HEIGHT}>^`, | |
`-gravity`, | |
`center`, | |
`-extent`, | |
`${THUMB_200_WIDTH}x${THUMB_200_HEIGHT}>`, | |
tempLocalThumbIcon | |
] | |
) | |
}) | |
.then(() => { console.log('Thumbnail created at', tempLocalThumbIcon) | |
// Uploading the Thumbnail. | |
return bucket.upload(tempLocalThumbIcon, { | |
destination: thumbIconPath, | |
metadata: metadata | |
}) | |
}) | |
// Finish upload | |
.then(() => { | |
console.log('Thumbnails uploaded to Storage') | |
// Once the image has been uploaded delete the local files to free up disk space. | |
fs.unlinkSync(tempLocalFile) | |
fs.unlinkSync(tempLocalThumbLarge) | |
fs.unlinkSync(tempLocalThumbSmall) | |
fs.unlinkSync(tempLocalThumbIcon) | |
// Get the Signed URLs for the thumbnail and original image. | |
const config = { | |
action: 'read', | |
expires: '03-01-2500', | |
} | |
return Promise.all([ | |
thumbLargeFile.getSignedUrl(config), | |
thumbSmallFile.getSignedUrl(config), | |
thumbIconFile.getSignedUrl(config), | |
file.getSignedUrl(config) | |
]) | |
}) | |
.then((results) => { | |
console.log('Got Signed URLs.') | |
const thumbLargeResult = results[0] | |
const thumbSmallResult = results[1] | |
const thumbIconResult = results[2] | |
const originalResult = results[3] | |
const thumbLargeFileUrl = thumbLargeResult[0] | |
const thumbSmallFileUrl = thumbSmallResult[0] | |
const thumbIconFileUrl = thumbIconResult[0] | |
const fileUrl = originalResult[0] | |
// Add the URLs to the Database | |
return admin.database().ref('images').push({ | |
oryginal: { | |
name: fileName, | |
url: fileUrl | |
}, | |
large: { | |
name: `${THUMB_LARGE_PREFIX}${fileName}`, | |
url: thumbLargeFileUrl | |
}, | |
small: { | |
name: `${THUMB_SMALL_PREFIX}${fileName}`, | |
url: thumbSmallFileUrl | |
}, | |
icon: { | |
name: `${THUMB_ICON_PREFIX}${fileName}`, | |
url: thumbIconFileUrl | |
} | |
}) | |
}) | |
.then(() => console.log('Thumbnail URLs saved to database.')) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment