使用 Node.js 进行图像压缩

2025-06-05

使用 Node.js 进行图像压缩

目前,我感觉市场越来越倾向于使用第三方服务来构成我们流程的一部分。最常见的服务之一就是压缩图像。

但是,我将展示,使用一个简单的Express.js API,我们可以上传图像、更改 Mime 类型并减小其大小。

我觉得我不需要讨论 Express.js,因为每个使用 Node.js 的人都用过这个框架。今天我主要讲一下multersharp

如今,上传图片是所有应用程序最基本的操作之一。Multer 是一个处理 multipart/form-data 的中间件,主要用于文件上传。将 Express.js 与 multer 结合使用,我们可以轻松实现文件上传功能。

Sharp 是 Node.js 的一个模块,用于将各种格式和各种尺寸的图像转换为较小的尺寸,而不必担心颜色空间、通道和 alpha 透明度,因为所有这些都得到了正确处理。

本例中使用的图像格式是WebP,它的压缩率比 png 和 jpg 更高,有助于更快地加载网页。而且所有浏览器都支持 WebP 。

如何使用

首先,我们将在 Node.js 中创建一个新项目,然后安装必要的依赖项:

# We will use the default values.
npm init -y

# Necessary dependencies.
npm install express multer sharp
Enter fullscreen mode Exit fullscreen mode

之后我们将创建一个简单的api:

const express = require("express");

const app = express();

app.get("/", (req, res) => {
 return res.json({ message: "Hello world 🔥🇵🇹" });
});

app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

一旦应用程序正常运行,我们将继续配置 multer。如果您查看过 multer 文档,我相信您已经看到我们可以通过两种方式保存图像:DiskStorage 或 MemoryStorage。

在本例中,我们将使用 MemoryStorage,因为我们希望访问 multer 提供的缓冲区。此外,我们还将使用 Express.js 的静态函数,以便稍后提供图像。

const express = require("express");
const multer = require("multer");

const app = express();
const storage = multer.memoryStorage();
const upload = multer({ storage });

app.use(express.static("./uploads"));

app.get("/", (req, res) => {
 return res.json({ message: "Hello world 🔥🇵🇹" });
});

app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

之后,我们将创建一个端点以使用 POST 动词发出 http 请求,但是我们将添加中间件上传,并且我们将只上传一个我们称之为“图片”的文件。

app.post("/", upload.single("picture"), async (req, res) => {
 // The logic goes here.
});
Enter fullscreen mode Exit fullscreen mode

下一步是检查工作区中是否存在“uploads”文件夹。如果不存在,我们需要 Node.js 为我们创建它。为此,我们需要访问文件系统,因此我们将使用fs模块。

app.post("/", upload.single("picture"), async (req, res) => {
 fs.access("./uploads", (error) => {
   if (error) {
     fs.mkdirSync("./uploads");
   }
 });
 // Even more logic goes here.
});
Enter fullscreen mode Exit fullscreen mode

现在我们可以开始使用 sharp 了,但首先我想创建一个随机字符串,放在图像名称之前,因为多张图片可能同名,所以最好谨慎处理。在本例中,我使用了时间戳(为了更容易理解),但理想情况下,应该使用一个 16 个字符的随机字符串。然后,我们将通过 multer 访问缓冲区图像的原始名称。

app.post("/", upload.single("picture"), async (req, res) => {
 fs.access("./uploads", (error) => {
   if (error) {
     fs.mkdirSync("./uploads");
   }
 });
 const { buffer, originalname } = req.file;
 const timestamp = new Date().toISOString();
 const ref = `${timestamp}-${originalname}.webp`;
 // Even more logic goes here.
});
Enter fullscreen mode Exit fullscreen mode

现在只需将图像缓冲区传递给 sharp,然后配置所需的质量、所需的格式以及文件的存储位置。在本例中,我希望将文件存储在“uploads”文件夹中,并使用我们指定的名称(ref变量)。

app.post("/", upload.single("picture"), async (req, res) => {
 fs.access("./uploads", (error) => {
   if (error) {
     fs.mkdirSync("./uploads");
   }
 });
 const { buffer, originalname } = req.file;
 const timestamp = new Date().toISOString();
 const ref = `${timestamp}-${originalname}.webp`;
 await sharp(buffer)
   .webp({ quality: 20 })
   .toFile("./uploads/" + ref);
 // Almost finished...
});
Enter fullscreen mode Exit fullscreen mode

最后但同样重要的一点是,我将创建一个名为link的变量,它将成为我们在浏览器中查看新图像的 url。

最终代码应该如下:

const express = require("express");
const multer = require("multer");
const sharp = require("sharp");
const fs = require("fs");

const app = express();
const storage = multer.memoryStorage();
const upload = multer({ storage });

app.use(express.static("./uploads"));

app.get("/", (req, res) => {
  return res.json({ message: "Hello world 🔥🇵🇹" });
});

app.post("/", upload.single("picture"), async (req, res) => {
  fs.access("./uploads", (error) => {
    if (error) {
      fs.mkdirSync("./uploads");
    }
  });
  const { buffer, originalname } = req.file;
  const timestamp = new Date().toISOString();
  const ref = `${timestamp}-${originalname}.webp`;
  await sharp(buffer)
    .webp({ quality: 20 })
    .toFile("./uploads/" + ref);
  const link = `http://localhost:3000/${ref}`;
  return res.json({ link });
});

app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

只需使用您最喜欢的 http 客户端(在本例中我使用了Insomnia),并且不要忘记使用 multipart/form-data 发送图像,并且字段的名称必须是“图片”,类型是文件。

像这样:

截屏

你呢?

您最喜欢的图像格式是什么?

文章来源:https://dev.to/franciscomendes10866/image-compression-with-node-js-4d7h
PREV
使用 React Hook Form 和 Yup 进行表单验证 让我们开始编码 你呢
NEXT
如何在 Node.js 中使用 ZeroMQ 发布/订阅模式