Generating thumbnails

We created upload and download routes, but they do nothing to the image other than storing it locally. Picking on our first thumbnail route, let's change our download route to be able to tell us the size we want for the image:

app.param("width", (req, res, next, width) => {
req.width = +width;

return next();
});

app.param("height", (req, res, next, height) => {
req.height = +height;

return next();
});

We start by defining two parameters, width, and height. These are numbers, so we'll assume they can be casted to a number type and stored in the request object.

Since we want to be able to specify sizes, let's create different routes using the route parameters we just introduced. To keep our code DRY, let's create a function to download the image and enable us to avoid repeating a very similar code. Our function will be able to handle optional resize:

function download_image(req, res) {
fs.access(req.localpath, fs.constants.R_OK , (err) => {
if (err) return res.status(404).end();

let image = sharp(req.localpath);

if (req.width && req.height) {
image.ignoreAspectRatio();
}

if (req.width || req.height) {
image.resize(req.width, req.height);
}

res.setHeader("Content-Type", "image/" +
path.extname(req.image).substr(1));

image.pipe(res);
});
}

Our function first starts by checking whether the image exists. This will avoid the sharp module from throwing for non-existent images. We then initialize the image processing by passing its local path. We then do something interesting:

if (req.width && req.height) {
image.ignoreAspectRatio();
}

First, if we receive both width and height, we tell sharp to ignore aspect ratio and resize as we tell it. Otherwise, it would maintain aspect ratio and center the image in the final size. You can check the difference by commenting out those first three lines:

if (req.width || req.height) {
image.resize(req.width, req.height);
}

Second, if we receive one of the width or height parameters, we resize the image. We can resize with only one of the parameters. The sharp module is also able to resize using only one of the parameters if the other is undefined, so the line just works and will maintain aspect ratio.

We then just do what we did before: set the content type response header and send the image to the user. Now, we can create multiple routes for this function.

We'll allow three different download scenarios:

  • A particular fixed-size image
  • An aspect ratio resize by passing only width or height
  • A full-size image

For the first scenario, we'll use our previous width and height parameters:

app.get("/uploads/:width(\d+)x:height(\d+)-:image", download_image);

This will allow a route address similar to the following:

For the second scenario, we'll use similar routes, where the missing parameter is replaced by an underscore:

app.get("/uploads/_x:height(\d+)-:image", download_image);
app.get("/uploads/:width(\d+)x_-:image", download_image);

These will allow routes similar to the one as follows:

For the third and final scenario, we'll keep the same route:

app.get("/uploads/:image", download_image);

These four routes must be defined in this order. This is important because route parameters are based on regular expressions and they're greedy, so we need to define our more complicated routes first, and then the simpler ones.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset