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