Nicolas Garnier
8 years ago
5 changed files with 127 additions and 0 deletions
@ -0,0 +1,26 @@ |
|||
# Automatically Generate Thumbnails |
|||
|
|||
This sample demonstrates how to automatically generate thumbnails for each images that are uploaded to Firebase Storage. |
|||
|
|||
|
|||
## Functions Code |
|||
|
|||
See file [functions/index.js](functions/index.js) for the thumbnail generation code. |
|||
|
|||
The thumbnail generation is performed using ImagMagick which is installed by default on all Firebase Functions. This is a CLI so we execute the command from node using the [child-process-promise](https://www.npmjs.com/package/child-process-promise) package. The image is first downloaded locally from the Firebase Storage bucket to the `tmp` folder using the [google-cloud](https://github.com/GoogleCloudPlatform/google-cloud-node) SDK. |
|||
|
|||
The dependencies are listed in [functions/package.json](functions/package.json). |
|||
|
|||
|
|||
## Trigger rules |
|||
|
|||
The function triggers on upload of any file to the Firebase Functions bucket. |
|||
|
|||
|
|||
## Deploy and test |
|||
|
|||
To deploy and test the sample: |
|||
|
|||
- Create a Firebase project on the [Firebase Console](https://console.firebase.google.com) and visit the **Storage** tab. |
|||
- Deploy your project using `firebase deploy` |
|||
- Go to the Firebase Console **Storage** tab and upload an image. After a short time an thumbnail image with the same name but a `thumb_` prefix will be created in the same folder (make sure you refresh the UI to see the new file). |
@ -0,0 +1 @@ |
|||
{} |
@ -0,0 +1,82 @@ |
|||
/** |
|||
* Copyright 2016 Google Inc. All Rights Reserved. |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for t`he specific language governing permissions and
|
|||
* limitations under the License. |
|||
*/ |
|||
'use strict'; |
|||
|
|||
const functions = require('firebase-functions'); |
|||
const mkdirp = require('mkdirp-promise'); |
|||
const gcs = require('@google-cloud/storage')(); |
|||
const exec = require('child-process-promise').exec; |
|||
const LOCAL_TMP_FOLDER = '/tmp/'; |
|||
|
|||
// Max height and width of the thumbnail in pixels.
|
|||
const THUMB_MAX_HEIGHT = 200; |
|||
const THUMB_MAX_WIDTH = 200; |
|||
// 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. |
|||
*/ |
|||
exports.generateThumbnail = functions.storage().onChange(event => { |
|||
const filePath = event.data.name; |
|||
const filePathSplit = filePath.split('/'); |
|||
const fileName = filePathSplit.pop(); |
|||
const fileDir = filePathSplit.join('/') + (filePathSplit.length > 0 ? '/' : ''); |
|||
const thumbFilePath = `${fileDir}${THUMB_PREFIX}${fileName}`; |
|||
const tempLocalDir = `${LOCAL_TMP_FOLDER}${fileDir}`; |
|||
const tempLocalFile = `${tempLocalDir}${fileName}`; |
|||
const tempLocalThumbFile = `${LOCAL_TMP_FOLDER}${thumbFilePath}`; |
|||
|
|||
// Exit if this is triggered on a file that is not an image.
|
|||
if (!event.data.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; |
|||
} |
|||
|
|||
// Exit if this is a move or deletion event.
|
|||
if (event.data.resourceState === 'not_exists') { |
|||
console.log('This is a deletion event.'); |
|||
return null; |
|||
} |
|||
|
|||
// Create the temp directory where the storage file will be downloaded.
|
|||
return mkdirp(tempLocalDir).then(() => { |
|||
// Download file from bucket.
|
|||
const bucket = gcs.bucket(event.data.bucket); |
|||
return bucket.file(filePath).download({ |
|||
destination: tempLocalFile |
|||
}).then(() => { |
|||
console.log('The file has been downloaded to', tempLocalFile); |
|||
// Generate a thumbnail using ImageMagick.
|
|||
return exec(`convert "${tempLocalFile}" -thumbnail '${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>' "${tempLocalThumbFile}"`).then(() => { |
|||
console.log('Thumbnail created at', tempLocalThumbFile); |
|||
// Uploading the Thumbnail.
|
|||
return bucket.upload(tempLocalThumbFile, { |
|||
destination: thumbFilePath |
|||
}).then(() => { |
|||
console.log('Thumbnail uploaded to Storage at', filePath); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
@ -0,0 +1,12 @@ |
|||
{ |
|||
"name": "functions", |
|||
"description": "Firebase Functions", |
|||
"dependencies": { |
|||
"@google-cloud/storage": "^0.4.0", |
|||
"child-process-promise": "^2.2.0", |
|||
"firebase": "^3.6.0", |
|||
"firebase-functions": "https://storage.googleapis.com/firebase-preview-drop/node/firebase-functions/firebase-functions-preview.latest.tar.gz", |
|||
"mkdirp": "^0.5.1", |
|||
"mkdirp-promise": "^4.0.0" |
|||
} |
|||
} |
Loading…
Reference in new issue