Learn how to build a Firebase Cloud Function that can resize images to multiple thumbnail sizes from a storage bucket. 

Functions Master Course with 40% Discount: https://goo.gl/jimk75

Or enroll for free by upgrading to PRO https://angularfirebase.com/pro/

Full lesson https://angularfirebase.com/lessons/image-thumbnail-resizer-cloud-function/
2024-02-04T07:23:10.882Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
b0bbd4cd-c7fb-48c6-9fd4-e50c8ecd5a27
b40b16d821be90f00f574e73021bc1999d8f0db2c42b72ba925df8b50104d625
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Today, we're going to build a cloud function that's capable of resizing an image into multiple thumbnails after it's initially uploaded.
This is one of the most commonly needed features for a cloud storage bucket, but doing it requires some pretty advanced Node JS code.
In today's video, we'll build this cloud function from scratch and do everything we can to optimize performance for the fastest possible execution.
If you're new to the channel, like and subscribe.
And if you wanna really good at Cloud Functions, consider enrolling in my Cloud Functions master course, which was just released yesterday.
The course is free if you're already a pro member, but If not, I'll go ahead and leave a discount code in the video description as well.
To get started, I am assuming that you have the Firebase command line tools installed, then we can run Firebase init functions in any existing project.
I'm going to select TypeScript here, but you could also select JavaScript.
But I would recommend that you use the new Node JS 8 runtime because we'll be using a lot of asyncawait syntax here.
And that's not available in the default Node 6 runtime.
Once that's done, we can CD into the functions directory.
And then we have a couple of dependencies to install here.
The Cloud Functions environment by default doesn't have tools set up for you to download files from a storage bucket.
But we can install the Google Cloud Storage Node.
Js client to take care of that for us.
When a storage Cloud function is triggered, it doesn't give you access directly to the file.
But instead, it just gives you some information about the file that was uploaded.
So we'll need the Google Cloud Storage Library to actually download it and resize the image and then reupload those back to the bucket.
We're also going to install a library called Sharp because it's 4 to 5 times faster than the ImageMagick library that's installed in the Cloud Functions environment.
And if you've ever used ImageMagick in a Cloud Function before, you'll know that it's pretty cumbersome.
Sharp is just way more developer friendly.
It's promise based, and we'll be able to do all of our resizing with single line of code.
The last dependency I'll install is Node file system extra.
This is a promise based version of the Node file system, which tends to be much more easy to work with in a Cloud Functions environment.
Let's go ahead and install that with NPM, then we'll have everything in place that we need to work with files in a developer friendly The goal of this function is to listen for a file upload to be finalized.
When that happens, it will take the source file, Resize it into multiple different sizes that you can specify and then re upload them into that same directory in the bucket.
One thing that's really important to keep in mind here is that when you have a storage Cloud Function that gets triggered on Finalize, That will get triggered for every single file that gets uploaded to this bucket including the thumbnails that we upload from the function itself.
That's really important because we need to give our code a certain exit point to know when to not upload a file because otherwise, we'll end up in an infinite loop.
If you create an infinite loop, your bucket will end up with thousands of new files uploaded to it and it won't stop uploading until it reaches the quota limit.
And if you don't catch Early, you might rack up some unnecessary charges on your Firebase bill.
Now we'll go ahead and jump into the code.
And just to warn you, the most complicated thing about this function is keeping track of the different file paths between the local functions file system and the storage bucket.
First, we'll instantiate the storage client, which we'll use to download and upload files.
Then every Cloud Function has a temporary directory that you can write files to.
The way you access it is with this temp dir method from Node.
And then we'll also import a couple of helpers from Node.
Join allows us to join paths together, and directory name allows us to get the directory from a file name.
And lastly, we'll bring in Sharp and FS Extra that we installed earlier.
We can give the cloud function a name of generate thumbs, And we'll have it run on the onFinalize event on the storage bucket, which just means that a file was fully uploaded somewhere in the bucket.
We'll be awaiting a whole bunch of different promises in this function.
So we'll make the callback on the function itself an async function.
We need to tell the Cloud Storage client which bucket to use to upload and download files, which we can just get from the object that triggered this function.
Then we have a handful of different variables that we need to define here just to keep track of the paths in the storage bucket and in the local system.
We can get the full path to the file in the bucket by calling Object Name.
Then we'll make a reference to the file name as well.
And we'll also wanna make reference to the directory that this file came from because that's eventually where we're going to upload our thumbnails to.
Now we need to download the source file to a working directory, and then we'll also need to save our thumbnails in a working directory temporarily as well.
So what I'm going to do is create a new directory and a temporary directory called thumbs because we'll eventually want to delete this once we exit the function just to clean everything up.
And lastly, I'll I'll define a path for where we're going to download the source image, which I'll just call source dot PNG.
At this point, we need to set up our breakpoint to avoid causing an infinite loop.
The concept is exactly the same as a recursive function in programming fundamentals.
We want to exit from this function early if it's been triggered by an image that's already been sized.
And we'll figure that out by using this thumb at keyword.
If that string is present in the file name, then we just want to exit because we know that it's already been resized.
And And at this point, we can also check if the Content Type is not an image.
In that case, we'll also want to exit early.
You can exit from a function by just returning false And that will prevent the execution of any code that comes after it.
Now that we have the initial setup done, we just have a series of steps to go through that are pretty straightforward if you look at them step by The first one is we need to make sure that our working directory exists.
Otherwise, we'll get an error if we try to use it.
And we can do that with FS Insuredirectory with our directory path.
Now that we know the directory exists, we'll go ahead and download the source file to that working 3, which we'll do with the GCS library.
We can await the bucket file to be downloaded to the path that we defined in that working After the file is downloaded, the 3rd step is to resize it to the thumbnail sizes that we want.
And then we'll wanna set up an array of promises that represent the upload operations for each one of those thumbnails.
There are different ways you can do this, but what I'm going to do is set up an array of different thumbnail sizes.
Then I'll map that array to an array of promises where each promise is an upload operation back to the bucket.
We can run those promises concurrently which should improve performance especially if you have a lot of different thumbnail sizes.
Each thumbnail will have the thumb at keyword followed by its size and then the original file name.
Then we'll define the full path to the working directory where we'll save that file.
When you call map on an array, it's just looping over its values.
So what we'll do here is await the Sharp library to resize the image and save it to the local file system, which we do by just passing it the original source image, call resize with the size we want it to be.
And you can also call a whole bunch of different other methods here in Sharp.
Resizing like this will crop the image from the center and size it to these dimensions.
Then we say to file with the thumbnail path.
And then the last thing we'll do in this map operation is return the bucket upload with this newly saved file.
Then we'll set the destination to the original file's destination with this new file name.
So that gives us an array of promises.
Now the only thing we have to do is run them which we could do by saying await Promise All with these upload promises.
That will run the uploads concurrently.
And then once that's complete, the last step is to just delete these files from the file system since they're no longer needed.
So as the 5th and final step, we'll go ahead and return from the function with FS remove the working directory.
Now Now let's go ahead and deploy the function so we can test it out.
Now any files that get uploaded to storage will automatically get a series of thumbnails generated for them.
And the performance should be pretty solid.
In most cases, I've seen latency of about 1 or 2 seconds, but performance really depends on the size of the file that was uploaded and also the number of thumbnails that you're generating.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and Subscribe and don't forget to check out the Cloud Functions Master Course.
I'd love to get your feedback and hear additional Cloud Functions topics that you'd like to see covered in the future.
Thanks for watching, and I'll talk to you soon.

Speaker 0: Today, we're going to build a cloud function that's capable of resizing an image into multiple thumbnails after it's initially uploaded. This is one of the most commonly needed features for a cloud storage bucket, but doing it requires some pretty advanced Node JS code. In today's video, we'll build this cloud function from scratch and do everything we can to optimize performance for the fastest possible execution. If you're new to the channel, like and subscribe. And if you wanna really good at Cloud Functions, consider enrolling in my Cloud Functions master course, which was just released yesterday.

The course is free if you're already a pro member, but If not, I'll go ahead and leave a discount code in the video description as well. To get started, I am assuming that you have the Firebase command line tools installed, then we can run Firebase init functions in any existing project. I'm going to select TypeScript here, but you could also select JavaScript. But I would recommend that you use the new Node JS 8 runtime because we'll be using a lot of asyncawait syntax here. And that's not available in the default Node 6 runtime.

Once that's done, we can CD into the functions directory. And then we have a couple of dependencies to install here. The Cloud Functions environment by default doesn't have tools set up for you to download files from a storage bucket. But we can install the Google Cloud Storage Node. Js client to take care of that for us.

When a storage Cloud function is triggered, it doesn't give you access directly to the file. But instead, it just gives you some information about the file that was uploaded. So we'll need the Google Cloud Storage Library to actually download it and resize the image and then reupload those back to the bucket. We're also going to install a library called Sharp because it's 4 to 5 times faster than the ImageMagick library that's installed in the Cloud Functions environment. And if you've ever used ImageMagick in a Cloud Function before, you'll know that it's pretty cumbersome.

Sharp is just way more developer friendly. It's promise based, and we'll be able to do all of our resizing with single line of code. The last dependency I'll install is Node file system extra. This is a promise based version of the Node file system, which tends to be much more easy to work with in a Cloud Functions environment. Let's go ahead and install that with NPM, then we'll have everything in place that we need to work with files in a developer friendly The goal of this function is to listen for a file upload to be finalized.

When that happens, it will take the source file, Resize it into multiple different sizes that you can specify and then re upload them into that same directory in the bucket. One thing that's really important to keep in mind here is that when you have a storage Cloud Function that gets triggered on Finalize, That will get triggered for every single file that gets uploaded to this bucket including the thumbnails that we upload from the function itself. That's really important because we need to give our code a certain exit point to know when to not upload a file because otherwise, we'll end up in an infinite loop. If you create an infinite loop, your bucket will end up with thousands of new files uploaded to it and it won't stop uploading until it reaches the quota limit. And if you don't catch Early, you might rack up some unnecessary charges on your Firebase bill.

Now we'll go ahead and jump into the code. And just to warn you, the most complicated thing about this function is keeping track of the different file paths between the local functions file system and the storage bucket. First, we'll instantiate the storage client, which we'll use to download and upload files. Then every Cloud Function has a temporary directory that you can write files to. The way you access it is with this temp dir method from Node.

And then we'll also import a couple of helpers from Node. Join allows us to join paths together, and directory name allows us to get the directory from a file name. And lastly, we'll bring in Sharp and FS Extra that we installed earlier. We can give the cloud function a name of generate thumbs, And we'll have it run on the onFinalize event on the storage bucket, which just means that a file was fully uploaded somewhere in the bucket. We'll be awaiting a whole bunch of different promises in this function.

So we'll make the callback on the function itself an async function. We need to tell the Cloud Storage client which bucket to use to upload and download files, which we can just get from the object that triggered this function. Then we have a handful of different variables that we need to define here just to keep track of the paths in the storage bucket and in the local system. We can get the full path to the file in the bucket by calling Object Name. Then we'll make a reference to the file name as well.

And we'll also wanna make reference to the directory that this file came from because that's eventually where we're going to upload our thumbnails to. Now we need to download the source file to a working directory, and then we'll also need to save our thumbnails in a working directory temporarily as well. So what I'm going to do is create a new directory and a temporary directory called thumbs because we'll eventually want to delete this once we exit the function just to clean everything up. And lastly, I'll I'll define a path for where we're going to download the source image, which I'll just call source dot PNG. At this point, we need to set up our breakpoint to avoid causing an infinite loop.

The concept is exactly the same as a recursive function in programming fundamentals. We want to exit from this function early if it's been triggered by an image that's already been sized. And we'll figure that out by using this thumb at keyword. If that string is present in the file name, then we just want to exit because we know that it's already been resized. And And at this point, we can also check if the Content Type is not an image.

In that case, we'll also want to exit early. You can exit from a function by just returning false And that will prevent the execution of any code that comes after it. Now that we have the initial setup done, we just have a series of steps to go through that are pretty straightforward if you look at them step by The first one is we need to make sure that our working directory exists. Otherwise, we'll get an error if we try to use it. And we can do that with FS Insuredirectory with our directory path.

Now that we know the directory exists, we'll go ahead and download the source file to that working 3, which we'll do with the GCS library. We can await the bucket file to be downloaded to the path that we defined in that working After the file is downloaded, the 3rd step is to resize it to the thumbnail sizes that we want. And then we'll wanna set up an array of promises that represent the upload operations for each one of those thumbnails. There are different ways you can do this, but what I'm going to do is set up an array of different thumbnail sizes. Then I'll map that array to an array of promises where each promise is an upload operation back to the bucket.

We can run those promises concurrently which should improve performance especially if you have a lot of different thumbnail sizes. Each thumbnail will have the thumb at keyword followed by its size and then the original file name. Then we'll define the full path to the working directory where we'll save that file. When you call map on an array, it's just looping over its values. So what we'll do here is await the Sharp library to resize the image and save it to the local file system, which we do by just passing it the original source image, call resize with the size we want it to be.

And you can also call a whole bunch of different other methods here in Sharp. Resizing like this will crop the image from the center and size it to these dimensions. Then we say to file with the thumbnail path. And then the last thing we'll do in this map operation is return the bucket upload with this newly saved file. Then we'll set the destination to the original file's destination with this new file name.

So that gives us an array of promises. Now the only thing we have to do is run them which we could do by saying await Promise All with these upload promises. That will run the uploads concurrently. And then once that's complete, the last step is to just delete these files from the file system since they're no longer needed. So as the 5th and final step, we'll go ahead and return from the function with FS remove the working directory.

Now Now let's go ahead and deploy the function so we can test it out. Now any files that get uploaded to storage will automatically get a series of thumbnails generated for them. And the performance should be pretty solid. In most cases, I've seen latency of about 1 or 2 seconds, but performance really depends on the size of the file that was uploaded and also the number of thumbnails that you're generating. I'm gonna go ahead and wrap things up there.

If this video helped you, please like and Subscribe and don't forget to check out the Cloud Functions Master Course. I'd love to get your feedback and hear additional Cloud Functions topics that you'd like to see covered in the future. Thanks for watching, and I'll talk to you soon.
Today, we're going to build a cloud function that's capable of resizing an image into multiple thumbnails after it's initially uploaded. This is one of the most commonly needed features for a cloud storage bucket, but doing it requires some pretty advanced Node JS code. In today's video, we'll build this cloud function from scratch and do everything we can to optimize performance for the fastest possible execution. If you're new to the channel, like and subscribe. And if you wanna really good at Cloud Functions, consider enrolling in my Cloud Functions master course, which was just released yesterday. The course is free if you're already a pro member, but If not, I'll go ahead and leave a discount code in the video description as well. To get started, I am assuming that you have the Firebase command line tools installed, then we can run Firebase init functions in any existing project. I'm going to select TypeScript here, but you could also select JavaScript. But I would recommend that you use the new Node JS 8 runtime because we'll be using a lot of asyncawait syntax here. And that's not available in the default Node 6 runtime. Once that's done, we can CD into the functions directory. And then we have a couple of dependencies to install here. The Cloud Functions environment by default doesn't have tools set up for you to download files from a storage bucket. But we can install the Google Cloud Storage Node. Js client to take care of that for us. When a storage Cloud function is triggered, it doesn't give you access directly to the file. But instead, it just gives you some information about the file that was uploaded. So we'll need the Google Cloud Storage Library to actually download it and resize the image and then reupload those back to the bucket. We're also going to install a library called Sharp because it's 4 to 5 times faster than the ImageMagick library that's installed in the Cloud Functions environment.
And if you've ever used ImageMagick in a Cloud Function before, you'll know that it's pretty cumbersome. Sharp is just way more developer friendly. It's promise based, and we'll be able to do all of our resizing with single line of code. The last dependency I'll install is Node file system extra.
software
software development
This is a promise based version of the Node file system, which tends to be much more easy to work with in a Cloud Functions environment.
Let's go ahead and install that with NPM, then we'll have everything in place that we need to work with files in a developer friendly The goal of this function is to listen for a file upload to be finalized. When that happens, it will take the source file, Resize it into multiple different sizes that you can specify and then re upload them into that same directory in the bucket.
software development
One thing that's really important to keep in mind here is that when you have a storage Cloud Function that gets triggered on Finalize, That will get triggered for every single file that gets uploaded to this bucket including the thumbnails that we upload from the function itself. That's really important because we need to give our code a certain exit point to know when to not upload a file because otherwise, we'll end up in an infinite loop. If you create an infinite loop, your bucket will end up with thousands of new files uploaded to it and it won't stop uploading until it reaches the quota limit. And if you don't catch Early, you might rack up some unnecessary charges on your Firebase bill. Now we'll go ahead and jump into the code. And just to warn you, the most complicated thing about this function is keeping track of the different file paths between the local functions file system and the storage bucket. First, we'll instantiate the storage client, which we'll use to download and upload files. Then every Cloud Function has a temporary directory that you can write files to. The way you access it is with this temp dir method from Node. And then we'll also import a couple of helpers from Node. Join allows us to join paths together, and directory name allows us to get the directory from a file name. And lastly, we'll bring in Sharp and FS Extra that we installed earlier. We can give the cloud function a name of generate thumbs, And we'll have it run on the onFinalize event on the storage bucket, which just means that a file was fully uploaded somewhere in the bucket. We'll be awaiting a whole bunch of different promises in this function. So we'll make the callback on the function itself an async function. We need to tell the Cloud Storage client which bucket to use to upload and download files, which we can just get from the object that triggered this function. Then we have a handful of different variables that we need to define here just to keep track of the paths in the storage bucket and in the local system. We can get the full path to the file in the bucket by calling Object Name. Then we'll make a reference to the file name as well. And we'll also wanna make reference to the directory that this file came from because that's eventually where we're going to upload our thumbnails to. Now we need to download the source file to a working directory, and then we'll also need to save our thumbnails in a working directory temporarily as well. So what I'm going to do is create a new directory and a temporary directory called thumbs because we'll eventually want to delete this once we exit the function just to clean everything up.
And lastly, I'll I'll define a path for where we're going to download the source image, which I'll just call source dot PNG. At this point, we need to set up our breakpoint to avoid causing an infinite loop. The concept is exactly the same as a recursive function in programming fundamentals.
software
We want to exit from this function early if it's been triggered by an image that's already been sized. And we'll figure that out by using this thumb at keyword. If that string is present in the file name, then we just want to exit because we know that it's already been resized. And And at this point, we can also check if the Content Type is not an image. In that case, we'll also want to exit early. You can exit from a function by just returning false And that will prevent the execution of any code that comes after it. Now that we have the initial setup done, we just have a series of steps to go through that are pretty straightforward if you look at them step by The first one is we need to make sure that our working directory exists. Otherwise, we'll get an error if we try to use it. And we can do that with FS Insuredirectory with our directory path. Now that we know the directory exists, we'll go ahead and download the source file to that working 3, which we'll do with the GCS library. We can await the bucket file to be downloaded to the path that we defined in that working After the file is downloaded, the 3rd step is to resize it to the thumbnail sizes that we want. And then we'll wanna set up an array of promises that represent the upload operations for each one of those thumbnails. There are different ways you can do this, but what I'm going to do is set up an array of different thumbnail sizes. Then I'll map that array to an array of promises where each promise is an upload operation back to the bucket. We can run those promises concurrently which should improve performance especially if you have a lot of different thumbnail sizes. Each thumbnail will have the thumb at keyword followed by its size and then the original file name. Then we'll define the full path to the working directory where we'll save that file. When you call map on an array, it's just looping over its values. So what we'll do here is await the Sharp library to resize the image and save it to the local file system, which we do by just passing it the original source image, call resize with the size we want it to be. And you can also call a whole bunch of different other methods here in Sharp. Resizing like this will crop the image from the center and size it to these dimensions. Then we say to file with the thumbnail path. And then the last thing we'll do in this map operation is return the bucket upload with this newly saved file. Then we'll set the destination to the original file's destination with this new file name. So that gives us an array of promises. Now the only thing we have to do is run them which we could do by saying await Promise All with these upload promises. That will run the uploads concurrently. And then once that's complete, the last step is to just delete these files from the file system since they're no longer needed. So as the 5th and final step, we'll go ahead and return from the function with FS remove the working directory. Now Now let's go ahead and deploy the function so we can test it out. Now any files that get uploaded to storage will automatically get a series of thumbnails generated for them. And the performance should be pretty solid.
In most cases, I've seen latency of about 1 or 2 seconds, but performance really depends on the size of the file that was uploaded and also the number of thumbnails that you're generating. I'm gonna go ahead and wrap things up there. If this video helped you, please like and Subscribe and don't forget to check out the Cloud Functions Master Course.
multimedia
I'd love to get your feedback and hear additional Cloud Functions topics that you'd like to see covered in the future. Thanks for watching, and I'll talk to you soon.
Today, we're going to build a cloud function that's capable of resizing an image into multiple thumbnails after it's initially uploaded. This is one of the most commonly needed features for a cloud storage bucket, but doing it requires some pretty advanced Node JS code. In today's video, we'll build this cloud function from scratch and do everything we can to optimize performance for the fastest possible execution. If you're new to the channel, like and subscribe. And if you wanna really good at Cloud Functions, consider enrolling in my Cloud Functions master course, which was just released yesterday. The course is free if you're already a pro member, but If not, I'll go ahead and leave a discount code in the video description as well. To get started, I am assuming that you have the Firebase command line tools installed, then we can run Firebase init functions in any existing project. I'm going to select TypeScript here, but you could also select JavaScript. But I would recommend that you use the new Node JS 8 runtime because we'll be using a lot of asyncawait syntax here. And that's not available in the default Node 6 runtime. Once that's done, we can CD into the functions directory. And then we have a couple of dependencies to install here. The Cloud Functions environment by default doesn't have tools set up for you to download files from a storage bucket. But we can install the Google Cloud Storage Node. Js client to take care of that for us. When a storage Cloud function is triggered, it doesn't give you access directly to the file. But instead, it just gives you some information about the file that was uploaded. So we'll need the Google Cloud Storage Library to actually download it and resize the image and then reupload those back to the bucket. We're also going to install a library called Sharp because it's 4 to 5 times faster than the ImageMagick library that's installed in the Cloud Functions environment. And if you've ever used ImageMagick in a Cloud Function before, you'll know that it's pretty cumbersome. Sharp is just way more developer friendly. It's promise based, and we'll be able to do all of our resizing with single line of code. The last dependency I'll install is Node file system extra. This is a promise based version of the Node file system, which tends to be much more easy to work with in a Cloud Functions environment. Let's go ahead and install that with NPM, then we'll have everything in place that we need to work with files in a developer friendly The goal of this function is to listen for a file upload to be finalized. When that happens, it will take the source file, Resize it into multiple different sizes that you can specify and then re upload them into that same directory in the bucket. One thing that's really important to keep in mind here is that when you have a storage Cloud Function that gets triggered on Finalize, That will get triggered for every single file that gets uploaded to this bucket including the thumbnails that we upload from the function itself. That's really important because we need to give our code a certain exit point to know when to not upload a file because otherwise, we'll end up in an infinite loop. If you create an infinite loop, your bucket will end up with thousands of new files uploaded to it and it won't stop uploading until it reaches the quota limit. And if you don't catch Early, you might rack up some unnecessary charges on your Firebase bill. Now we'll go ahead and jump into the code. And just to warn you, the most complicated thing about this function is keeping track of the different file paths between the local functions file system and the storage bucket. First, we'll instantiate the storage client, which we'll use to download and upload files. Then every Cloud Function has a temporary directory that you can write files to. The way you access it is with this temp dir method from Node. And then we'll also import a couple of helpers from Node. Join allows us to join paths together, and directory name allows us to get the directory from a file name. And lastly, we'll bring in Sharp and FS Extra that we installed earlier. We can give the cloud function a name of generate thumbs, And we'll have it run on the onFinalize event on the storage bucket, which just means that a file was fully uploaded somewhere in the bucket. We'll be awaiting a whole bunch of different promises in this function. So we'll make the callback on the function itself an async function. We need to tell the Cloud Storage client which bucket to use to upload and download files, which we can just get from the object that triggered this function. Then we have a handful of different variables that we need to define here just to keep track of the paths in the storage bucket and in the local system. We can get the full path to the file in the bucket by calling Object Name. Then we'll make a reference to the file name as well. And we'll also wanna make reference to the directory that this file came from because that's eventually where we're going to upload our thumbnails to. Now we need to download the source file to a working directory, and then we'll also need to save our thumbnails in a working directory temporarily as well. So what I'm going to do is create a new directory and a temporary directory called thumbs because we'll eventually want to delete this once we exit the function just to clean everything up. And lastly, I'll I'll define a path for where we're going to download the source image, which I'll just call source dot PNG. At this point, we need to set up our breakpoint to avoid causing an infinite loop. The concept is exactly the same as a recursive function in programming fundamentals. We want to exit from this function early if it's been triggered by an image that's already been sized. And we'll figure that out by using this thumb at keyword. If that string is present in the file name, then we just want to exit because we know that it's already been resized. And And at this point, we can also check if the Content Type is not an image. In that case, we'll also want to exit early. You can exit from a function by just returning false And that will prevent the execution of any code that comes after it. Now that we have the initial setup done, we just have a series of steps to go through that are pretty straightforward if you look at them step by The first one is we need to make sure that our working directory exists. Otherwise, we'll get an error if we try to use it. And we can do that with FS Insuredirectory with our directory path. Now that we know the directory exists, we'll go ahead and download the source file to that working 3, which we'll do with the GCS library. We can await the bucket file to be downloaded to the path that we defined in that working After the file is downloaded, the 3rd step is to resize it to the thumbnail sizes that we want. And then we'll wanna set up an array of promises that represent the upload operations for each one of those thumbnails. There are different ways you can do this, but what I'm going to do is set up an array of different thumbnail sizes. Then I'll map that array to an array of promises where each promise is an upload operation back to the bucket. We can run those promises concurrently which should improve performance especially if you have a lot of different thumbnail sizes. Each thumbnail will have the thumb at keyword followed by its size and then the original file name. Then we'll define the full path to the working directory where we'll save that file. When you call map on an array, it's just looping over its values. So what we'll do here is await the Sharp library to resize the image and save it to the local file system, which we do by just passing it the original source image, call resize with the size we want it to be. And you can also call a whole bunch of different other methods here in Sharp. Resizing like this will crop the image from the center and size it to these dimensions. Then we say to file with the thumbnail path. And then the last thing we'll do in this map operation is return the bucket upload with this newly saved file. Then we'll set the destination to the original file's destination with this new file name. So that gives us an array of promises. Now the only thing we have to do is run them which we could do by saying await Promise All with these upload promises. That will run the uploads concurrently. And then once that's complete, the last step is to just delete these files from the file system since they're no longer needed. So as the 5th and final step, we'll go ahead and return from the function with FS remove the working directory. Now Now let's go ahead and deploy the function so we can test it out. Now any files that get uploaded to storage will automatically get a series of thumbnails generated for them. And the performance should be pretty solid. In most cases, I've seen latency of about 1 or 2 seconds, but performance really depends on the size of the file that was uploaded and also the number of thumbnails that you're generating. I'm gonna go ahead and wrap things up there. If this video helped you, please like and Subscribe and don't forget to check out the Cloud Functions Master Course. I'd love to get your feedback and hear additional Cloud Functions topics that you'd like to see covered in the future. Thanks for watching, and I'll talk to you soon.
Today,
today
we're
we're
going
going
to
to
build
build
a
a
cloud
cloud
function
function
that's
that's
capable
capable
of
of
resizing
resizing
an
an
image
image
into
into
multiple
multiple
thumbnails
thumbnails
after
after
it's
it's
initially
initially
uploaded.
uploaded
This
this
is
is
one
one
of
of
the
the
most
most
commonly
commonly
needed
needed
features
features
for
for
a
a
cloud
cloud
storage
storage
bucket,
bucket
but
but
doing
doing
it
it
requires
requires
some
some
pretty
pretty
advanced
advanced
Node
node
JS
js
code.
code
In
in
today's
today's
video,
video
we'll
we'll
build
build
this
this
cloud
cloud
function
function
from
from
scratch
scratch
and
and
do
do
everything
everything
we
we
can
can
to
to
optimize
optimize
performance
performance
for
for
the
the
fastest
fastest
possible
possible
execution.
execution
If
if
you're
you're
new
new
to
to
the
the
channel,
channel
like
like
and
and
subscribe.
subscribe
And
and
if
if
you
you
wanna
wanna
really
really
good
good
at
at
Cloud
cloud
Functions,
functions
consider
consider
enrolling
enrolling
in
in
my
my
Cloud
cloud
Functions
functions
master
master
course,
course
which
which
was
was
just
just
released
released
yesterday.
yesterday
The
the
course
course
is
is
free
free
if
if
you're
you're
already
already
a
a
pro
pro
member,
member
but
but
If
if
not,
not
I'll
i'll
go
go
ahead
ahead
and
and
leave
leave
a
a
discount
discount
code
code
in
in
the
the
video
video
description
description
as
as
well.
well
To
to
get
get
started,
started
I
i
am
am
assuming
assuming
that
that
you
you
have
have
the
the
Firebase
firebase
command
command
line
line
tools
tools
installed,
installed
then
then
we
we
can
can
run
run
Firebase
firebase
init
init
functions
functions
in
in
any
any
existing
existing
project.
project
I'm
i'm
going
going
to
to
select
select
TypeScript
typescript
here,
here
but
but
you
you
could
could
also
also
select
select
JavaScript.
javascript
But
but
I
i
would
would
recommend
recommend
that
that
you
you
use
use
the
the
new
new
Node
node
JS
js
8
8
runtime
runtime
because
because
we'll
we'll
be
be
using
using
a
a
lot
lot
of
of
asyncawait
asyncawait
syntax
syntax
here.
here
And
and
that's
that's
not
not
available
available
in
in
the
the
default
default
Node
node
6
6
runtime.
runtime
Once
once
that's
that's
done,
done
we
we
can
can
CD
cd
into
into
the
the
functions
functions
directory.
directory
And
and
then
then
we
we
have
have
a
a
couple
couple
of
of
dependencies
dependencies
to
to
install
install
here.
here
The
the
Cloud
cloud
Functions
functions
environment
environment
by
by
default
default
doesn't
doesn't
have
have
tools
tools
set
set
up
up
for
for
you
you
to
to
download
download
files
files
from
from
a
a
storage
storage
bucket.
bucket
But
but
we
we
can
can
install
install
the
the
Google
google
Cloud
cloud
Storage
storage
Node.
node
Js
js
client
client
to
to
take
take
care
care
of
of
that
that
for
for
us.
us
When
when
a
a
storage
storage
Cloud
cloud
function
function
is
is
triggered,
triggered
it
it
doesn't
doesn't
give
give
you
you
access
access
directly
directly
to
to
the
the
file.
file
But
but
instead,
instead
it
it
just
just
gives
gives
you
you
some
some
information
information
about
about
the
the
file
file
that
that
was
was
uploaded.
uploaded
So
so
we'll
we'll
need
need
the
the
Google
google
Cloud
cloud
Storage
storage
Library
library
to
to
actually
actually
download
download
it
it
and
and
resize
resize
the
the
image
image
and
and
then
then
reupload
reupload
those
those
back
back
to
to
the
the
bucket.
bucket
We're
we're
also
also
going
going
to
to
install
install
a
a
library
library
called
called
Sharp
sharp
because
because
it's
it's
4
4
to
to
5
5
times
times
faster
faster
than
than
the
the
ImageMagick
imagemagick
library
library
that's
that's
installed
installed
in
in
the
the
Cloud
cloud
Functions
functions
environment.
environment
And
and
if
if
you've
you've
ever
ever
used
used
ImageMagick
imagemagick
in
in
a
a
Cloud
cloud
Function
function
before,
before
you'll
you'll
know
know
that
that
it's
it's
pretty
pretty
cumbersome.
cumbersome
Sharp
sharp
is
is
just
just
way
way
more
more
developer
developer
friendly.
friendly
It's
it's
promise
promise
based,
based
and
and
we'll
we'll
be
be
able
able
to
to
do
do
all
all
of
of
our
our
resizing
resizing
with
with
single
single
line
line
of
of
code.
code
The
the
last
last
dependency
dependency
I'll
i'll
install
install
is
is
Node
node
file
file
system
system
extra.
extra
This
this
is
is
a
a
promise
promise
based
based
version
version
of
of
the
the
Node
node
file
file
system,
system
which
which
tends
tends
to
to
be
be
much
much
more
more
easy
easy
to
to
work
work
with
with
in
in
a
a
Cloud
cloud
Functions
functions
environment.
environment
Let's
let's
go
go
ahead
ahead
and
and
install
install
that
that
with
with
NPM,
npm
then
then
we'll
we'll
have
have
everything
everything
in
in
place
place
that
that
we
we
need
need
to
to
work
work
with
with
files
files
in
in
a
a
developer
developer
friendly
friendly
The
the
goal
goal
of
of
this
this
function
function
is
is
to
to
listen
listen
for
for
a
a
file
file
upload
upload
to
to
be
be
finalized.
finalized
When
when
that
that
happens,
happens
it
it
will
will
take
take
the
the
source
source
file,
file
Resize
resize
it
it
into
into
multiple
multiple
different
different
sizes
sizes
that
that
you
you
can
can
specify
specify
and
and
then
then
re
re
upload
upload
them
them
into
into
that
that
same
same
directory
directory
in
in
the
the
bucket.
bucket
One
one
thing
thing
that's
that's
really
really
important
important
to
to
keep
keep
in
in
mind
mind
here
here
is
is
that
that
when
when
you
you
have
have
a
a
storage
storage
Cloud
cloud
Function
function
that
that
gets
gets
triggered
triggered
on
on
Finalize,
finalize
That
that
will
will
get
get
triggered
triggered
for
for
every
every
single
single
file
file
that
that
gets
gets
uploaded
uploaded
to
to
this
this
bucket
bucket
including
including
the
the
thumbnails
thumbnails
that
that
we
we
upload
upload
from
from
the
the
function
function
itself.
itself
That's
that's
really
really
important
important
because
because
we
we
need
need
to
to
give
give
our
our
code
code
a
a
certain
certain
exit
exit
point
point
to
to
know
know
when
when
to
to
not
not
upload
upload
a
a
file
file
because
because
otherwise,
otherwise
we'll
we'll
end
end
up
up
in
in
an
an
infinite
infinite
loop.
loop
If
if
you
you
create
create
an
an
infinite
infinite
loop,
loop
your
your
bucket
bucket
will
will
end
end
up
up
with
with
thousands
thousands
of
of
new
new
files
files
uploaded
uploaded
to
to
it
it
and
and
it
it
won't
won't
stop
stop
uploading
uploading
until
until
it
it
reaches
reaches
the
the
quota
quota
limit.
limit
And
and
if
if
you
you
don't
don't
catch
catch
Early,
early
you
you
might
might
rack
rack
up
up
some
some
unnecessary
unnecessary
charges
charges
on
on
your
your
Firebase
firebase
bill.
bill
Now
now
we'll
we'll
go
go
ahead
ahead
and
and
jump
jump
into
into
the
the
code.
code
And
and
just
just
to
to
warn
warn
you,
you
the
the
most
most
complicated
complicated
thing
thing
about
about
this
this
function
function
is
is
keeping
keeping
track
track
of
of
the
the
different
different
file
file
paths
paths
between
between
the
the
local
local
functions
functions
file
file
system
system
and
and
the
the
storage
storage
bucket.
bucket
First,
first
we'll
we'll
instantiate
instantiate
the
the
storage
storage
client,
client
which
which
we'll
we'll
use
use
to
to
download
download
and
and
upload
upload
files.
files
Then
then
every
every
Cloud
cloud
Function
function
has
has
a
a
temporary
temporary
directory
directory
that
that
you
you
can
can
write
write
files
files
to.
to
The
the
way
way
you
you
access
access
it
it
is
is
with
with
this
this
temp
temp
dir
dir
method
method
from
from
Node.
node
And
and
then
then
we'll
we'll
also
also
import
import
a
a
couple
couple
of
of
helpers
helpers
from
from
Node.
node
Join
join
allows
allows
us
us
to
to
join
join
paths
paths
together,
together
and
and
directory
directory
name
name
allows
allows
us
us
to
to
get
get
the
the
directory
directory
from
from
a
a
file
file
name.
name
And
and
lastly,
lastly
we'll
we'll
bring
bring
in
in
Sharp
sharp
and
and
FS
fs
Extra
extra
that
that
we
we
installed
installed
earlier.
earlier
We
we
can
can
give
give
the
the
cloud
cloud
function
function
a
a
name
name
of
of
generate
generate
thumbs,
thumbs
And
and
we'll
we'll
have
have
it
it
run
run
on
on
the
the
onFinalize
onfinalize
event
event
on
on
the
the
storage
storage
bucket,
bucket
which
which
just
just
means
means
that
that
a
a
file
file
was
was
fully
fully
uploaded
uploaded
somewhere
somewhere
in
in
the
the
bucket.
bucket
We'll
we'll
be
be
awaiting
awaiting
a
a
whole
whole
bunch
bunch
of
of
different
different
promises
promises
in
in
this
this
function.
function
So
so
we'll
we'll
make
make
the
the
callback
callback
on
on
the
the
function
function
itself
itself
an
an
async
async
function.
function
We
we
need
need
to
to
tell
tell
the
the
Cloud
cloud
Storage
storage
client
client
which
which
bucket
bucket
to
to
use
use
to
to
upload
upload
and
and
download
download
files,
files
which
which
we
we
can
can
just
just
get
get
from
from
the
the
object
object
that
that
triggered
triggered
this
this
function.
function
Then
then
we
we
have
have
a
a
handful
handful
of
of
different
different
variables
variables
that
that
we
we
need
need
to
to
define
define
here
here
just
just
to
to
keep
keep
track
track
of
of
the
the
paths
paths
in
in
the
the
storage
storage
bucket
bucket
and
and
in
in
the
the
local
local
system.
system
We
we
can
can
get
get
the
the
full
full
path
path
to
to
the
the
file
file
in
in
the
the
bucket
bucket
by
by
calling
calling
Object
object
Name.
name
Then
then
we'll
we'll
make
make
a
a
reference
reference
to
to
the
the
file
file
name
name
as
as
well.
well
And
and
we'll
we'll
also
also
wanna
wanna
make
make
reference
reference
to
to
the
the
directory
directory
that
that
this
this
file
file
came
came
from
from
because
because
that's
that's
eventually
eventually
where
where
we're
we're
going
going
to
to
upload
upload
our
our
thumbnails
thumbnails
to.
to
Now
now
we
we
need
need
to
to
download
download
the
the
source
source
file
file
to
to
a
a
working
working
directory,
directory
and
and
then
then
we'll
we'll
also
also
need
need
to
to
save
save
our
our
thumbnails
thumbnails
in
in
a
a
working
working
directory
directory
temporarily
temporarily
as
as
well.
well
So
so
what
what
I'm
i'm
going
going
to
to
do
do
is
is
create
create
a
a
new
new
directory
directory
and
and
a
a
temporary
temporary
directory
directory
called
called
thumbs
thumbs
because
because
we'll
we'll
eventually
eventually
want
want
to
to
delete
delete
this
this
once
once
we
we
exit
exit
the
the
function
function
just
just
to
to
clean
clean
everything
everything
up.
up
And
and
lastly,
lastly
I'll
i'll
I'll
i'll
define
define
a
a
path
path
for
for
where
where
we're
we're
going
going
to
to
download
download
the
the
source
source
image,
image
which
which
I'll
i'll
just
just
call
call
source
source
dot
dot
PNG.
png
At
at
this
this
point,
point
we
we
need
need
to
to
set
set
up
up
our
our
breakpoint
breakpoint
to
to
avoid
avoid
causing
causing
an
an
infinite
infinite
loop.
loop
The
the
concept
concept
is
is
exactly
exactly
the
the
same
same
as
as
a
a
recursive
recursive
function
function
in
in
programming
programming
fundamentals.
fundamentals
We
we
want
want
to
to
exit
exit
from
from
this
this
function
function
early
early
if
if
it's
it's
been
been
triggered
triggered
by
by
an
an
image
image
that's
that's
already
already
been
been
sized.
sized
And
and
we'll
we'll
figure
figure
that
that
out
out
by
by
using
using
this
this
thumb
thumb
at
at
keyword.
keyword
If
if
that
that
string
string
is
is
present
present
in
in
the
the
file
file
name,
name
then
then
we
we
just
just
want
want
to
to
exit
exit
because
because
we
we
know
know
that
that
it's
it's
already
already
been
been
resized.
resized
And
and
And
and
at
at
this
this
point,
point
we
we
can
can
also
also
check
check
if
if
the
the
Content
content
Type
type
is
is
not
not
an
an
image.
image
In
in
that
that
case,
case
we'll
we'll
also
also
want
want
to
to
exit
exit
early.
early
You
you
can
can
exit
exit
from
from
a
a
function
function
by
by
just
just
returning
returning
false
false
And
and
that
that
will
will
prevent
prevent
the
the
execution
execution
of
of
any
any
code
code
that
that
comes
comes
after
after
it.
it
Now
now
that
that
we
we
have
have
the
the
initial
initial
setup
setup
done,
done
we
we
just
just
have
have
a
a
series
series
of
of
steps
steps
to
to
go
go
through
through
that
that
are
are
pretty
pretty
straightforward
straightforward
if
if
you
you
look
look
at
at
them
them
step
step
by
by
The
the
first
first
one
one
is
is
we
we
need
need
to
to
make
make
sure
sure
that
that
our
our
working
working
directory
directory
exists.
exists
Otherwise,
otherwise
we'll
we'll
get
get
an
an
error
error
if
if
we
we
try
try
to
to
use
use
it.
it
And
and
we
we
can
can
do
do
that
that
with
with
FS
fs
Insuredirectory
insuredirectory
with
with
our
our
directory
directory
path.
path
Now
now
that
that
we
we
know
know
the
the
directory
directory
exists,
exists
we'll
we'll
go
go
ahead
ahead
and
and
download
download
the
the
source
source
file
file
to
to
that
that
working
working
3,
3
which
which
we'll
we'll
do
do
with
with
the
the
GCS
gcs
library.
library
We
we
can
can
await
await
the
the
bucket
bucket
file
file
to
to
be
be
downloaded
downloaded
to
to
the
the
path
path
that
that
we
we
defined
defined
in
in
that
that
working
working
After
after
the
the
file
file
is
is
downloaded,
downloaded
the
the
3rd
3rd
step
step
is
is
to
to
resize
resize
it
it
to
to
the
the
thumbnail
thumbnail
sizes
sizes
that
that
we
we
want.
want
And
and
then
then
we'll
we'll
wanna
wanna
set
set
up
up
an
an
array
array
of
of
promises
promises
that
that
represent
represent
the
the
upload
upload
operations
operations
for
for
each
each
one
one
of
of
those
those
thumbnails.
thumbnails
There
there
are
are
different
different
ways
ways
you
you
can
can
do
do
this,
this
but
but
what
what
I'm
i'm
going
going
to
to
do
do
is
is
set
set
up
up
an
an
array
array
of
of
different
different
thumbnail
thumbnail
sizes.
sizes
Then
then
I'll
i'll
map
map
that
that
array
array
to
to
an
an
array
array
of
of
promises
promises
where
where
each
each
promise
promise
is
is
an
an
upload
upload
operation
operation
back
back
to
to
the
the
bucket.
bucket
We
we
can
can
run
run
those
those
promises
promises
concurrently
concurrently
which
which
should
should
improve
improve
performance
performance
especially
especially
if
if
you
you
have
have
a
a
lot
lot
of
of
different
different
thumbnail
thumbnail
sizes.
sizes
Each
each
thumbnail
thumbnail
will
will
have
have
the
the
thumb
thumb
at
at
keyword
keyword
followed
followed
by
by
its
its
size
size
and
and
then
then
the
the
original
original
file
file
name.
name
Then
then
we'll
we'll
define
define
the
the
full
full
path
path
to
to
the
the
working
working
directory
directory
where
where
we'll
we'll
save
save
that
that
file.
file
When
when
you
you
call
call
map
map
on
on
an
an
array,
array
it's
it's
just
just
looping
looping
over
over
its
its
values.
values
So
so
what
what
we'll
we'll
do
do
here
here
is
is
await
await
the
the
Sharp
sharp
library
library
to
to
resize
resize
the
the
image
image
and
and
save
save
it
it
to
to
the
the
local
local
file
file
system,
system
which
which
we
we
do
do
by
by
just
just
passing
passing
it
it
the
the
original
original
source
source
image,
image
call
call
resize
resize
with
with
the
the
size
size
we
we
want
want
it
it
to
to
be.
be
And
and
you
you
can
can
also
also
call
call
a
a
whole
whole
bunch
bunch
of
of
different
different
other
other
methods
methods
here
here
in
in
Sharp.
sharp
Resizing
resizing
like
like
this
this
will
will
crop
crop
the
the
image
image
from
from
the
the
center
center
and
and
size
size
it
it
to
to
these
these
dimensions.
dimensions
Then
then
we
we
say
say
to
to
file
file
with
with
the
the
thumbnail
thumbnail
path.
path
And
and
then
then
the
the
last
last
thing
thing
we'll
we'll
do
do
in
in
this
this
map
map
operation
operation
is
is
return
return
the
the
bucket
bucket
upload
upload
with
with
this
this
newly
newly
saved
saved
file.
file
Then
then
we'll
we'll
set
set
the
the
destination
destination
to
to
the
the
original
original
file's
file's
destination
destination
with
with
this
this
new
new
file
file
name.
name
So
so
that
that
gives
gives
us
us
an
an
array
array
of
of
promises.
promises
Now
now
the
the
only
only
thing
thing
we
we
have
have
to
to
do
do
is
is
run
run
them
them
which
which
we
we
could
could
do
do
by
by
saying
saying
await
await
Promise
promise
All
all
with
with
these
these
upload
upload
promises.
promises
That
that
will
will
run
run
the
the
uploads
uploads
concurrently.
concurrently
And
and
then
then
once
once
that's
that's
complete,
complete
the
the
last
last
step
step
is
is
to
to
just
just
delete
delete
these
these
files
files
from
from
the
the
file
file
system
system
since
since
they're
they're
no
no
longer
longer
needed.
needed
So
so
as
as
the
the
5th
5th
and
and
final
final
step,
step
we'll
we'll
go
go
ahead
ahead
and
and
return
return
from
from
the
the
function
function
with
with
FS
fs
remove
remove
the
the
working
working
directory.
directory
Now
now
Now
now
let's
let's
go
go
ahead
ahead
and
and
deploy
deploy
the
the
function
function
so
so
we
we
can
can
test
test
it
it
out.
out
Now
now
any
any
files
files
that
that
get
get
uploaded
uploaded
to
to
storage
storage
will
will
automatically
automatically
get
get
a
a
series
series
of
of
thumbnails
thumbnails
generated
generated
for
for
them.
them
And
and
the
the
performance
performance
should
should
be
be
pretty
pretty
solid.
solid
In
in
most
most
cases,
cases
I've
i've
seen
seen
latency
latency
of
of
about
about
1
1
or
or
2
2
seconds,
seconds
but
but
performance
performance
really
really
depends
depends
on
on
the
the
size
size
of
of
the
the
file
file
that
that
was
was
uploaded
uploaded
and
and
also
also
the
the
number
number
of
of
thumbnails
thumbnails
that
that
you're
you're
generating.
generating
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
Subscribe
subscribe
and
and
don't
don't
forget
forget
to
to
check
check
out
out
the
the
Cloud
cloud
Functions
functions
Master
master
Course.
course
I'd
i'd
love
love
to
to
get
get
your
your
feedback
feedback
and
and
hear
hear
additional
additional
Cloud
cloud
Functions
functions
topics
topics
that
that
you'd
you'd
like
like
to
to
see
see
covered
covered
in
in
the
the
future.
future
Thanks
thanks
for
for
watching,
watching
and
and
I'll
i'll
talk
talk
to
to
you
you
soon.
soon
success
The process of resizing images using the Cloud function uses the hungl file system and Azure cloud storage private virtual machine for faster performance and a better file cache. The use of the Cloud function for uploading and downloading files and setting up a callback on the function is recommended. The process is straightforward and involves defining file paths, storage, and media, setting up promises, and uploading files. The speaker provides examples of steps involved and recommends testing the code through AWS.
Image Resize Cloud Function
Today, we're going to build a cloud function that's capable of resizing an image into multiple thumbnails after it's initially uploaded. This is one of the most commonly needed features for a cloud storage bucket, but doing it requires some pretty advanced Node JS code. In today's video, we'll build this cloud function from scratch and do everything we can to optimize performance for the fastest possible execution. If you're new to the channel, like and subscribe. And if you wanna really good at Cloud Functions, consider enrolling in my Cloud Functions master course, which was just released yesterday. The course is free if you're already a pro member, but If not, I'll go ahead and leave a discount code in the video description as well. To get started, I am assuming that you have the Firebase command line tools installed, then we can run Firebase init functions in any existing project. I'm going to select TypeScript here, but you could also select JavaScript. But I would recommend that you use the new Node JS 8 runtime because we'll be using a lot of asyncawait syntax here. And that's not available in the default Node 6 runtime. Once that's done, we can CD into the functions directory. And then we have a couple of dependencies to install here. The Cloud Functions environment by default doesn't have tools set up for you to download files from a storage bucket. But we can install the Google Cloud Storage Node. Js client to take care of that for us. When a storage Cloud function is triggered, it doesn't give you access directly to the file. But instead, it just gives you some information about the file that was uploaded. So we'll need the Google Cloud Storage Library to actually download it and resize the image and then reupload those back to the bucket. We're also going to install a library called Sharp because it's 4 to 5 times faster than the ImageMagick library that's installed in the Cloud Functions environment. And if you've ever used ImageMagick in a Cloud Function before, you'll know that it's pretty cumbersome. Sharp is just way more developer friendly. It's promise based, and we'll be able to do all of our resizing with single line of code. The last dependency I'll install is Node file system extra. This is a promise based version of the Node file system, which tends to be much more easy to work with in a Cloud Functions environment. Let's go ahead and install that with NPM, then we'll have everything in place that we need to work with files in a developer friendly The goal of this function is to listen for a file upload to be finalized. When that happens, it will take the source file, Resize it into multiple different sizes that you can specify and then re upload them into that same directory in the bucket. One thing that's really important to keep in mind here is that when you have a storage Cloud Function that gets triggered on Finalize, That will get triggered for every single file that gets uploaded to this bucket including the thumbnails that we upload from the function itself. That's really important because we need to give our code a certain exit point to know when to not upload a file because otherwise, we'll end up in an infinite loop. If you create an infinite loop, your bucket will end up with thousands of new files uploaded to it and it won't stop uploading until it reaches the quota limit. And if you don't catch Early, you might rack up some unnecessary charges on your Firebase bill. Now we'll go ahead and jump into the code. And just to warn you, the most complicated thing about this function is keeping track of the different file paths between the local functions file system and the storage bucket. First, we'll instantiate the storage client, which we'll use to download and upload files. Then every Cloud Function has a temporary directory that you can write files to. The way you access it is with this temp dir method from Node. And then we'll also import a couple of helpers from Node. Join allows us to join paths together, and directory name allows us to get the directory from a file name. And lastly, we'll bring in Sharp and FS Extra that we installed earlier. We can give the cloud function a name of generate thumbs, And we'll have it run on the onFinalize event on the storage bucket, which just means that a file was fully uploaded somewhere in the bucket. We'll be awaiting a whole bunch of different promises in this function. So we'll make the callback on the function itself an async function. We need to tell the Cloud Storage client which bucket to use to upload and download files, which we can just get from the object that triggered this function. Then we have a handful of different variables that we need to define here just to keep track of the paths in the storage bucket and in the local system. We can get the full path to the file in the bucket by calling Object Name. Then we'll make a reference to the file name as well. And we'll also wanna make reference to the directory that this file came from because that's eventually where we're going to upload our thumbnails to. Now we need to download the source file to a working directory, and then we'll also need to save our thumbnails in a working directory temporarily as well. So what I'm going to do is create a new directory and a temporary directory called thumbs because we'll eventually want to delete this once we exit the function just to clean everything up. And lastly, I'll I'll define a path for where we're going to download the source image, which I'll just call source dot PNG. At this point, we need to set up our breakpoint to avoid causing an infinite loop. The concept is exactly the same as a recursive function in programming fundamentals. We want to exit from this function early if it's been triggered by an image that's already been sized. And we'll figure that out by using this thumb at keyword. If that string is present in the file name, then we just want to exit because we know that it's already been resized. And And at this point, we can also check if the Content Type is not an image. In that case, we'll also want to exit early. You can exit from a function by just returning false And that will prevent the execution of any code that comes after it. Now that we have the initial setup done, we just have a series of steps to go through that are pretty straightforward if you look at them step by The first one is we need to make sure that our working directory exists. Otherwise, we'll get an error if we try to use it. And we can do that with FS Insuredirectory with our directory path. Now that we know the directory exists, we'll go ahead and download the source file to that working 3, which we'll do with the GCS library. We can await the bucket file to be downloaded to the path that we defined in that working After the file is downloaded, the 3rd step is to resize it to the thumbnail sizes that we want. And then we'll wanna set up an array of promises that represent the upload operations for each one of those thumbnails. There are different ways you can do this, but what I'm going to do is set up an array of different thumbnail sizes. Then I'll map that array to an array of promises where each promise is an upload operation back to the bucket. We can run those promises concurrently which should improve performance especially if you have a lot of different thumbnail sizes. Each thumbnail will have the thumb at keyword followed by its size and then the original file name. Then we'll define the full path to the working directory where we'll save that file. When you call map on an array, it's just looping over its values. So what we'll do here is await the Sharp library to resize the image and save it to the local file system, which we do by just passing it the original source image, call resize with the size we want it to be. And you can also call a whole bunch of different other methods here in Sharp. Resizing like this will crop the image from the center and size it to these dimensions. Then we say to file with the thumbnail path. And then the last thing we'll do in this map operation is return the bucket upload with this newly saved file. Then we'll set the destination to the original file's destination with this new file name. So that gives us an array of promises. Now the only thing we have to do is run them which we could do by saying await Promise All with these upload promises. That will run the uploads concurrently. And then once that's complete, the last step is to just delete these files from the file system since they're no longer needed. So as the 5th and final step, we'll go ahead and return from the function with FS remove the working directory. Now Now let's go ahead and deploy the function so we can test it out. Now any files that get uploaded to storage will automatically get a series of thumbnails generated for them. And the performance should be pretty solid. In most cases, I've seen latency of about 1 or 2 seconds, but performance really depends on the size of the file that was uploaded and also the number of thumbnails that you're generating. I'm gonna go ahead and wrap things up there. If this video helped you, please like and Subscribe and don't forget to check out the Cloud Functions Master Course. I'd love to get your feedback and hear additional Cloud Functions topics that you'd like to see covered in the future. Thanks for watching, and I'll talk to you soon.
The process of resizing images using the Cloud function uses the hungl file system and Azure cloud storage private virtual machine for faster performance and a better file cache. The use of the Cloud function for uploading and downloading files and setting up a callback on the function is recommended. The process is straightforward and involves defining file paths, storage, and media, setting up promises, and uploading files. The speaker provides examples of steps involved and recommends testing the code through AWS.