How can I compress and resize user-uploaded images on the client side?
Unanswered
pratik posted this in #help-forum
pratikOP
Yeah it's not a NextJS specific issue, but I don't wanna post it on SO and get destroyed.
First, I didn't even consider image compression and stuff. But, after using my app for a while, I noticed when I upload 4-5 big images (each 10-15 MB), it crashes/reloads the page. It's happening because I'm rendering all those big pictures directly on the web page. So to prevent that, I needed to compress those pictures before rendering. First I went with [react-image-file-resizer](https://www.npmjs.com/package/react-image-file-resizer), which was good enough for me. It accepts
At this point, I became confused. The Web Worker is running in a different thread, but it's still running in the browser, right? So all the browser APIs should be available. Or I'm getting something wrong here?
You might ask, why not create an API dedicated only to image compression and use a NodeJS library? Well, I could do that, but my app is deployed in Vercel, and as many of you know, Vercel has a payload limit of 4.5MB. So I cannot send a total of 200MB+ images to my API endpoint in the production
So, do u have any idea why I can't access the Image constructor in the Web Worker? or can u suggest some other similar library u know that can help me achieve my requirement?
Any kinda help will be appreciated...
First, I didn't even consider image compression and stuff. But, after using my app for a while, I noticed when I upload 4-5 big images (each 10-15 MB), it crashes/reloads the page. It's happening because I'm rendering all those big pictures directly on the web page. So to prevent that, I needed to compress those pictures before rendering. First I went with [react-image-file-resizer](https://www.npmjs.com/package/react-image-file-resizer), which was good enough for me. It accepts
maxWidth, maxHeight, and quality parameters, and these are the main things I needed to change in the pictures. But while using it, I noticed my app gets stuck while the compression is running. It was happening because of the default single-threaded behavior of JavaScript and the compression process is a heavy task. So as expected, I went with [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). But then while running the compression (inside Web Worker), I was getting an error "Image is not defined". The react-image-file-resizer library uses the [Image](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image) ConstructorAt this point, I became confused. The Web Worker is running in a different thread, but it's still running in the browser, right? So all the browser APIs should be available. Or I'm getting something wrong here?
You might ask, why not create an API dedicated only to image compression and use a NodeJS library? Well, I could do that, but my app is deployed in Vercel, and as many of you know, Vercel has a payload limit of 4.5MB. So I cannot send a total of 200MB+ images to my API endpoint in the production
So, do u have any idea why I can't access the Image constructor in the Web Worker? or can u suggest some other similar library u know that can help me achieve my requirement?
Any kinda help will be appreciated...
14 Replies
The payload limit is only an issue if you’re not using presigned URLs
If you’re hosting images in an s3 compatible service
You ask your backend to speak with s3 and return a url
@linesofcode The payload limit is only an issue if you’re not using presigned URLs
pratikOP
I'm uploading the user-selected images in my db. so i don't think i can have pre-signed URLs. or i got u wrong?
You ask your backend to speak with s3 and return a url
Provide that url to the frontend
Your frontend then uploads directly to that url
The lambda than resizes the image using whatever node or python libs
If you’re using aws then you can setup a lambda which runs whenever an object hits the bucket
And writes it back into the bucket
Holding images in your db is a bit of an anti pattern
Especially if your images are large or you plan on scaling or you have a lot of traffic
pratikOP
well, I'm not using s3 or aws. i'm using a BAAS product where I need to upload my images in the bucket. and afaik, that BAAS doesn't provide any way to get a pre-signed URL for a file
@linesofcode The lambda than resizes the image using whatever node or python libs
pratikOP
I'm resizing the images after uploaded in the bucket. but I mainly need the compression on the client side, only for previewing the images to the user before uploading, in this case