在node.js中需要图像处理方面的帮助



例如,有什么方法可以在需要时获得调整大小的图像吗。想要做的就是/image.jpg给我的是原始图像,但image_200x200.jpg给我调整大小的图像,宽度和高度为200px。我想让它,使图像在渲染时调整大小,这样我就不必存储调整大小的图像。提前感谢

有办法吗

是的,有。但你必须意识到,这样做,每次请求时都会调整图像的大小。如果你希望你的网站上有大量的流量,这不是一个可持续的解决方案,除非你真的把这些调整大小的图像存储在某种缓存中。

即使你缓存了它们,也要注意,如果没有任何URL签名(确保URL是由你的服务器发布的(,恶意用户可能会想通过每次使用随机大小的请求来SPAM你的服务器,以迫使你的服务器进行调整大小操作,并使其不堪重负。

既然这已经解决了,让我们试着找到一个解决方案。

我们如何在Express中发送请求

Express提供了一种提供静态文件的方法,当我们不需要调整大小时,我们可以保留这些文件。如果在此位置未找到文件,则将对照下一个路由进行检查。因此,在下一篇文章中,我们将在尝试匹配其他路线之前,先检查是否需要调整大小。我们可以通过使用匹配特定模式的正则表达式来定位这些正则表达式。

这个例子将匹配以CCD_ 1和"0"结尾的URL;jpeg"jpg";或";png";分机:

app.use(express.static(Path.join(__dirname, 'public'))); // If a file is found
app.use('/(*_\d+x\d+.(jpe?g|png))', resizingMiddleware); // If resizing is needed
// ... Other routes

中间件

中间件是Express在请求路由时调用的函数。在这种情况下,我们可以这样声明:

function resizingMiddleware(req, res, next)  {
const data = parseResizingURI(req.baseUrl); // Extract data from the URI
if (!data) { return next(); } // Could not parse the URI
// Get full file path in public directory
const path = Path.join(__dirname, 'public', data.path);
resizeImage(path, data.width, data.height)
.then(buffer => {
// Success. Send the image
res.set('Content-type', mime.lookup(path)); // using 'mime-types' package
res.send(buffer);
})
.catch(next); // File not found or resizing failed
}

正在从URI中提取数据

正如您在上面看到的,我使用了parseResizingURI来获取原始文件名以及请求的维度。让我们编写这个函数:

function limitNumberToRange(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function parseResizingURI(uri) {
// Attempt to extract some variables using Regex
const matches = uri.match(
/(?<path>.*/)(?<name>[^/]+)_(?<width>d+)x(?<height>d+)(?<extension>.[a-zd]+)$/i
);
if (matches) {
const { path, name, width, height, extension } = matches.groups;
return {
path: path + name + extension, // Original file path
width: limitNumberToRange(+width, 16, 2000),   // Ensure the size is in a range
height: limitNumberToRange(+height, 16, 2000), // so people don't try 999999999
extension: extension
};
}
return false;
}

调整图像大小

在中间件中,您可能还会看到一个resizeImage函数。让我们用sharp:来写

function resizeImage(path, width, height) {
return sharp(path).resize({
width,
height,
// Preserve aspect ratio, while ensuring dimensions are <= to those specified
fit: sharp.fit.inside,
}).toBuffer();
}

把它们放在一起

最后,我们得到以下代码:

// Don't forget to install all used packages:
// $ npm install --save mime-types express sharp
const Path = require('path');
const mime = require('mime-types')
const sharp = require('sharp');
const express = require('express');
const app = express();
// Existing files are sent through as-is
app.use(express.static(Path.join(__dirname, 'public')));
// Requests for resizing
app.use('/(*_\d+x\d+.(jpe?g|png))', resizingMiddleware);
// Other routes...
app.get('/', (req, res) => { res.send('Hello World!'); });
app.listen(3000);
function resizingMiddleware(req, res, next)  {
const data = parseResizingURI(req.baseUrl); // Extract data from the URI
if (!data) { return next(); } // Could not parse the URI
// Get full file path in public directory
const path = Path.join(__dirname, 'public', data.path);
resizeImage(path, data.width, data.height)
.then(buffer => {
// Success. Send the image
res.set('Content-type', mime.lookup(path)); // using 'mime-types' package
res.send(buffer);
})
.catch(next); // File not found or resizing failed
}
function resizeImage(path, width, height) {
return sharp(path).resize({
width,
height,
// Preserve aspect ratio, while ensuring dimensions are <= to those specified
fit: sharp.fit.inside,
}).toBuffer();
}
function limitNumberToRange(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function parseResizingURI(uri) {
// Attempt to extract some variables using Regex
const matches = uri.match(
/(?<path>.*/)(?<name>[^/]+)_(?<width>d+)x(?<height>d+)(?<extension>.[a-zd]+)$/i
);
if (matches) {
const { path, name, width, height, extension } = matches.groups;
return {
path: path + name + extension, // Original file path
width: limitNumberToRange(+width, 16, 2000),   // Ensure the size is in a range
height: limitNumberToRange(+height, 16, 2000), // so people don't try 999999999
extension: extension
};
}
return false;
}

最新更新