Possiamo creare thumbnail dinamiche in Node.js con il modulo gm.
Dobbiamo installare le librerie GraphicsMagick e ImageMagick. Sul server possiamo usare il package manager della nostra distro (i pacchetti sono imagemagick e graphicsmagick), mentre su macOS possiamo usare Homebrew o MacPorts (i nomi dei pacchetti sono gli stessi).
Quindi possiamo installare il modulo gm:
npm install gm --save
Gestiremo solo immagini JPEG e PNG sotto una specifica directory usando gli stream per ottimizzare la performance:
'use strict';
const path = require('path');
const ABSPATH = path.dirname(process.mainModule.filename);
const gm = require('gm');
const fs = require('fs');
const exists = (path) => {
try {
return fs.statSync(path).isFile();
} catch (e) {
return false;
}
};
const getFileExtension = (filename) => {
return filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 2);
};
class Media {
constructor(path) {
this.src = path;
}
isValidMedia(src) {
return /\.(jpe?g|png)$/.test(src);
}
isValidBaseDir(src) {
return /^\/public\/images/.test(src);
}
thumb(request, response) {
let image = ABSPATH + this.src;
if(this.isValidBaseDir(this.src) && this.isValidMedia(this.src) && exists(image)) {
let width = (request.query.w && /^\d+$/.test(request.query.w)) ? request.query.w : '150';
let height = (request.query.h && /^\d+$/.test(request.query.h)) ? request.query.h : '150';
let extension = getFileExtension(this.src);
let mime = (extension === 'jpeg' || extension === 'jpg') ? 'jpeg' : 'png';
response.type(mime);
gm(image).resize(width, height).stream().pipe(response);
} else {
response.sendStatus(404);
}
}
}
module.exports = Media;
In ExpressJS dobbiamo solo creare una route specifica:
'use strict';
const app = require('express')();
const Media = require('./classes/Media');
app.get('/thumb', (req, res) => {
if(req.query.src) {
let image = new Media(req.query.src);
image.thumb(req, res);
} else {
res.sendStatus(403);
}
});
app.listen(8080);
Ora possiamo usare un URL come http://localhost:8080/thumb/?src=/public/images/image.jpg&w=640&h=480.