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.

Places project icon

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.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Promises, and Asynchronous Javascript — Node.js

Code Kata #2 Find longest common prefix of given array of words!

Algolia Instantsearch.js infused with Angular 4

SSR vs CSR vs SSG in Next.js

Industry UsecasJAVASCRIPT

COVID-19 music series: Video performance of Hong Kong Taoist  Orchestra(在COVID-19疫情下香港道樂團的演出)

Firebase — Firestore Database Realtime Updates with React Hooks — useEffect

The Good and the Bad of ReactJS and React Native

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Casper Leerink

Casper Leerink

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

More from Medium

Prototype A React App with Firebase Authentication Quickly

How to use Bootstrap 5 with CDN in Nextjs?

How to use Bootstrap 5 with CDN in Nextjs By Rajdeep Singh

MEAN vs. MERN: Which Is the Best Tech Stack for Your Next Project?

Easy Typewriter Animation with TailwindCSS v3 in React