Image Manipulations Using Express

In this post by Diogo Resende, a Node.js expert, you’ll learn to create an image processing microservice. The tutorial starts with a simple thumbnail service and then goes on to show how to make some simple image transformations.

Express has a simple and useful layer on top of the default Node.js HTTP module. Create an empty folder, initialize the package.json file, and install Express. You can get the complete code for this article at https://gist.github.com/packtpartner/180024fd93e56451e8fba893b044d305

To help you get around images, use the sharp module, a very fast image manipulation tool for the modern web. It will allow you to easily transform and resize images in a simple serial interface. Install it now:

Start by exposing an address to return thumbnails. You’ll first need to define the default parameters. Later on, you’ll allow the user to change the default values. The service will run on port 3000 and will accept thumbnail requests on both PNG and JPEG formats. Here’s the not-so-simple service:

Start by getting access to both the express and sharp modules and then initialize the Express application:

Next, create a route to get an image, with a regular expression that will catch the address, /thumbnail.png and /thumbnail.jpg. Use the extension to ascertain what image type the user wants. Also, define some default parameters, such as sizes and colors:

Next, create an empty image using sharp:

Then, create an SVG file with an outer border, two crossing lines, and a text in the middle with the size of the image. Next, overlay the SVG on the empty image and output the result to the user:

Finally, initialize the service on port 3000:

Save the full code shown previously as imagini.js and run it on the console:

You can now head to your web browser and type the address of the service and you’ll see something like the following image:

You can now start making some changes. Change the default variables to something like this:

Restart the service and play with query parameters to see the result. Here’s an example of changing the width to 500 px, the border to 2 px, and the foreground color to cyan:

Well, it looks awesome but isn’t very useful as it just shows the same empty image. Though, perhaps, more applicable for prototyping, in the real world, it would be more useful if it could create thumbnails from uploaded images.

To do so, you must be able to:

  • Upload images, which should be stored somewhere
  • Check whether an image exists
  • Download an image thumbnail

To simplify, you’ll need to create dynamic routes in a specific path and use HTTP verbs (GET, POST, DELETE, and so on) to distinguish the actions. When uploading images, use POST, with the body having the image data. To check if an image exists, use HEAD.

Uploading images

First add the route to handle uploading images. Use a body parser module that will handle compressed requests automatically for you:

Include it along with the other core modules that you’ll need. Add these lines on the top of the service file:

You can now create the function that will handle the upload:

To expect an HTTP POST on the /uploads path, you must have an image with a maximum size of 10 MB:

Start by checking whether the image name ends with .png or .jpg. If not, reply with an HTTP 403 response code, which means forbidden:

Next, create a stream to the local file where you’ll save your image. The name of the file will be the name of the image. Also, store the image size, so you can return it to the user when you finish saving. This enables the microservice user to check if he’s received all the data.

Lastly, write the image to file and, after properly closing the stream, reply to the user with a JSON response with a status and a size property.

Don’t forget to create the uploads folder inside the microservice folder. Then, restart the service. Upload an image to the service using this command:

Here, you’re telling curl that you want to:

  • Send a POST request
  • Define the Content-Type header saying it’s a PNG image
  • Add the content of the example.png file inside the request body
  • Send the request to the /upload/example.png path of the microservice

After executing the command, you’ll receive a JSON response. The size matches the file:

You can’t see the image using the microservice just yet, but you can check it locally. You should have a copy of the file in the uploads folder. For reference, here’s the image used for the purposes of this tutorial:

Checking if an image exists in the folder

You can now create a route to check whether an image exists in the uploads folder. Use the HEAD verb. If you're not familiar with it, it's like a GET request, but without a body (no content). It's used to request only information (headers) from a path.

Look for a similar route, but, this time, handle HEAD requests only. This is a simple check. Just question whether the current process has read access to the local file.

If it does, reply with HTTP response code 200, which means Found. If not, reply with HTTP response code 404, which means Not Found:

Add the preceding code and restart the service.

If you use curl to check for the previously uploaded file, you'll receive something like this:

If you change the path to something else, you should receive something like this:

If you found this tutorial helpful, you can explore the book, Hands-On Microservices with Node.js by Diogo Resende. The book is an end-to-end guide on how to dismantle your monolith application and embrace the microservices architecture right from architecting your services and modeling them to integrating them in your application. So, if you’re a JavaScript developer seeking to build microservice architecture and move away from monolith applications, this Hands-On Microservices with Node.js is a must-have.