简体   繁体   中英

Render opmised images with Node.js and express with sharp or canvas

I am struggling to get images rendered with an optimised configuration using node and express with sharp .

I managed to create an upload method using Jimp that converts images larger than 2000px wide and larger than 2mb file size and it works fine, I came across dozens of libraries that do the same Jimp is more efficient in memory for what I built.

Basically II have in my liquid template engine like this:

<img src="{{i.images[0].path}}" alt="{{i.name}}">

I would like to create a router that reads the images from the MongoDB /projects/project route with the images array and pass the images back to the render optimised and resized as instructed in the configuration with sharp, I would like to further configure this method to maybe a middleware to work globally in the site with images with query params to render on demand also enhancing with device detection for a better performance download:

const request = require('request');
const fs = require("fs");
const path = require("path");
const sharp = require('sharp');

module.exports = (req, res, next) => {

    request(process.env.REQUEST_PATH + "/projects?projectType=Refurbishment%20and%20Extensions", (err, response, body) => {
        if (err) {
            console.log(err);
        } else {

            const contentData = JSON.parse(body);

            contentData.projects.forEach((value, key) => {
                if (value.images[0].path.length > 0) {
                    const readStream = fs.createReadStream(path.resolve("./" + value.images[0].path));
                    //const getBuffer = Buffer.from(path.resolve("./" + value.images[0].path));
                    const trasnform = sharp(readStream).resize(200, 200, {
                        fit: "contain"
                    }).jpeg({
                        quality: 20
                    }).toBuffer((err, data, info) => {
                        if (err) {
                            console.log(err)
                        } else {
                            console.log("BUFFERED RESIZED", info);
                            //console.log("BUFFER", data);
                        }
                    });
                    console.log(trasnform); //nothing working
                    readStream.pipe(trasnform).pipe(res);
                }
            });

            const data = {
                name: "Refurbishment and Extensions Projects",
                content: contentData
            };

            res.render('./refurbishment-and-extensions-projects', {
                page: data
            });

        }
    });

}

In some attempts it returned the info from Sharp with the image converted to buffer, I am not sure why but now I get an error [Error: Input file is missing] but there's a buffer to read!

At the moment I am not picky for a solution but regarding some performances test sharp.js or canvas.js would be great to be used, please give me some idea on this.

Issue resolved here thanks to Lovell creator of Sharp.

In order to render an image with sharp and pipe it correctly to the response you only pass the transformer in this case Sharp and its configurable functions, it looks like I was trying to pass the image again to the transformer and this returns an error Unexpected data on Writable Stream

I have made various changes to this code and opted to create a middleware to handle this across my application.

The final code I used looks like:

const express = require("express");
const router = express.Router();
const fs = require("fs");
const path = require("path");
const Sharp = require('sharp');

router.get('/:imageName', (req, res, next) => {

    const imagePath = "./" + req._parsedOriginalUrl.pathname; //req.originalUrl or req._parsedOriginalUrl.pathname

    if (req.query.format != null) {

        if (fs.existsSync(imagePath)) {

            const format = req.query.format ? req.query.format : "webp";
            const width = req.query.width ? parseInt(req.query.width) : null;
            const height = req.query.height ? parseInt(req.query.height) : null;
            const crop = req.query.crop ?  req.query.crop : "cover";

            const stream = fs.createReadStream(imagePath);

            const transform = Sharp().resize(width, height, {
                fit: crop
            }).toFormat(format, {
                quality: 85
            });

            res.set('Content-Type', `image/${format}`);
            stream.pipe(transform).pipe(res);

            return stream;

        }//ensuring the file path is correct
    }
    next();
});

module.exports = router;

If you came to get this issue you need to understand a lot more about Node Filesystem, Streams and the pipe function how they work to fully understand what you are doing. ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM