React Firebase: Resize image on client side (for free)

For a recent project I created, I had to upload images to Firebase storage. When these images are uploaded I also wanted to create a very small thumbnail image that I use as a marker in a custom google maps icon. You can view the project here.

For this tutorial, I assume you already have some knowledge of firebase and react and know how to initialize a firebase project and enable firebase storage.

When I first started to search how I could achieve this, most solutions involve using Firebase functions, to create the thumbnail on the server side triggered by my image upload. This was all going according to plan until I started to upload my firebase function. Then I got the message I needed to upgrade my firebase plan to a paid plan.

Cheap and broke as I am, I went looking for another solution…

(If you are interested in how functions work and/or you are not as cheap as me, I would suggest you follow this great article.)

It turns out you can resize your images on the client side as well, using the canvas element, and as a react developer, you don’t even have to worry about implementing this. You can just use the React Image File Resizer npm package.

npm install react-image-file-resizer

It works like this:

Get image file from website visitor.

In one of your react components, implement some way to get an image from the user either by using an input tag:

<input 
name=”image”
type=”file”
accept=”image/jpeg, image/png”
onChange={(e) => handleUpload(e.target.files[0])}
/>

or by defining an area where someone can drop their image, I have made this into a component:

The result is the same and a function (in this case handleUpload / callback) can be called whenever a new file is selected or dropped with the image file as the argument. In the case of the input, you get the image file from the event.target.files[0]. Selecting the first file. (I am assuming 1 image upload at a time, so there is always only one file)

Resizing the image

Now we get to the actual resizing. I am making a thumbnail with a width of 30 or a height of 30, depending on the orientation of the image. (portrait = height of 30, landscape = width of 30).

The basic way to resize the file from the website visitor is by importing the Resizer from react-image-file-resizer.

In the callback we get a uri we can use to upload to firebase. But first I want to remodel this a little bit so it works as a promised based function and I can use it in my async uploading function.

const resizeFile = (file) =>
new Promise((resolve) => {
Resizer.imageFileResizer(file, 30, 30, “PNG”, 100, 0, (uri) => {
resolve(uri);
});
});

This has the same functionality but just makes it so that in my async function I can simply get the uri by calling:

const uri = await resizeFile(file);
console.log(uri);

Now I can upload the thumbnail and the full image to firebase. I am assuming you have already initialized your firebase app and enabled storage in your firebase project.

Note that I am using the firebase web API 9.0 which is in beta, because it descreases the loading time for people coming to my website as I can import only the functions from firebase that I need instead of the whole package. For example, below I am importing all the functions I need to store my images.

Upload Function

Note that because the resizer returns a uri of type ‘base64’ which is different from the ‘file’ returned from the input or the dropfile component. Therefore we use the uploadString method from firebase for the thumbnail with a third argument of ‘data_url’ and the uploadBytes method for the full image just providing it the file from the input/dropfile.

It is important to wrap this all in a try — catch statement to prevent the site from breaking if something goes wrong during the upload, for example when I reach my maximum quota on my free firebase plan and I still have to upgrade my firebase plan😬.

Thank you for reading, write a comment if there is anything unclear or if you have any questions!

My website

I am an artist / creator / web developer, I like to create web applications and designs for art projects and artists.