User Woes of Image Uploading
You’ve signed up on a new website and you are just crusing through filling out all your information. Then it comes time to upload a portrait of yourself.
You meticulously comb through all your pictures to find the best one and you finally try to upload it. “Image must be smaller than…” frustrated, you either give up or if you care, then you figure out some way to shrink the image.
What if the website could resize the image for you and you never had to see an error that causes more work?
Let’s Do Some Research
Any time we want to tackle a problem with some code, there’s some work we need to do up front: research.
This is a lot of back and forth with a search engine. Many blog posts will explain everything and the process it takes to get from point A to point B.
- how to resize an image with canvas
- how to convert canvas to an image
- what is a dataURL
- what is a blob
A lot of writing software is looking stuff up. 90% of that is figuring out what stuff to look up, so some of those search terms are valuable keywords to keep in mind when doing work like this. They will also help you if you decide to expand on the code I’ve written in the example below.
For this demo, you can choose an image to resize. It’ll show the original image next to the resized image. I’ve set the resized image’s maximum width or height to be 480px and it’ll try to be the same
MIME type as the original, but
canvas has some limitations.
Try to run the code locally on your computer and play with the code. A few suggestions to try out:
- Change the maximum dimension
- Resize an image using a URL
- Add a way to specify the image dimension using an
<input type="text" />element
For this image resizer, we wrote it as a module that exports three functions:
loadFile(file): takes a
Fileas an argument and returns it as a
resizeImage(imageSource, maxDimensionSize): takes an
imageSourceof either a
dataURLor a path to an image
URLand returns an object with both a
dataURLversion of the resized image.
maxDimensionSizewill be either the maximum width or height of the resized image, based on whichever is larger.
getResizedImageFromFile(file, maxDimensionSize): takes a
All three of these functions are asynchronous, which means the code can run in parallel with other code. It’s worth noting because there is some nuance with asynchronous vs synchronous code.
In our code, we’ve used quite a few Promises. They can be a whole topic on their own, but at their core, Promises are one way of handling asyncronous code.
Imagine you want to hang out with your best friend. You say, “Dinner tonight?” and they respond, “I promise to get back to you.” You continue to go about your day as usual, as if we can do that while waiting for a text, until they respond. They can either accept and then you add dinner to your calendar or they reject it and you figure out other plans.
You might also notice
await in there.
async is a way of saying, “This function can run in parallel” and
await can only be used in an
async function. When you use
await, you’re telling the code to not continue until until you get a response back, which is why it needs to run in an
async, parallel executing function.
To incorporate this with the first example, you text your friend, “Dinner tonight?” and then stare at your phone for 2 hours until they respond back to you. The day itself continued to move along, but you were just anxiously awaiting their response and incapable of doing anything else, just like me whenever I send a text.
At this point, hopefully you’ve got a better understanding of asyncronous code with Promises,
await. The image resizing code was a practical excuse to get you introduced to a complex topic. I find a lot of code examples end up being contrived and I ask, “But when would I actually use that?” If you have a practical use case for Function Generators, please let me know.
At a minimum, at least you now have some code you can send to some website administrator the next time you get an “Image is too large” error when you’re just trying to post a selfie.