当前位置:首页 > 技术 > 正文内容

Express中使用Multer中间件处理文件上传

代码老兵 技术 2

文件上传是现代Web应用的常见需求。无论是用户头像、简历提交还是图库图片,Node.js和Express后端都必须能够安全地接收、处理和存储文件。

由于HTTP协议基于文本传输,二进制文件需要特殊处理。本文将详细讲解如何使用Express中最流行且可靠的文件上传中间件库Multer来处理文件上传。

为什么文件上传需要中间件

当用户在网页上提交表单时,数据通常以application/x-www-form-urlencodedapplication/json格式编码。但处理文件时,表单编码方式必须切换为multipart/form-data

multipart/form-data是什么?

  • 标准数据: HTML表单中的文本字段只包含简单的键值对。

  • 多部分数据: 当附加文件时,请求体会被分割成多个"部分"(因此得名),每个部分代表表单的不同字段,包括文件本身的二进制数据。

Express本身无法解析这种格式,所以我们需要一个解析中间件(如Multer)来拦截请求、提取文件数据,并使其在路由处理器中可用。

Multer简介

Multer是一个用于处理multipart/form-data的Node.js中间件,主要用于文件上传。它基于busboy构建,具有很高的处理效率。

  • 重要提示: Multer不会处理非多部分格式的表单(必须是multipart/form-data)。

项目初始化

在开始编写代码之前,先初始化Node.js项目并安装依赖:

npm init -y
npm install express multer
  1. 单文件上传

从最简单的场景开始:上传单个文件。假设表单中有一个name属性为avatar的输入框。

上传请求的生命周期如下:

实现代码

创建server.js文件,设置基本的Express服务器和Multer配置:

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

const app = express();
const upload = multer({ dest: 'uploads/' });

// 提供HTML表单(简单测试端点)
app.get('/', (req, res) => {
  res.send(`
    <form action="/upload" method="POST" enctype="multipart/form-data">
      <input type="file" name="avatar" />
      <button type="submit">上传文件</button>
    </form>
  `);
});

// 单文件上传端点
app.post('/upload', upload.single('avatar'), (req, res) => {
  // req.file包含上传文件的信息
  // req.body包含文本字段(如表单中其他文本输入)

  if (!req.file) {
    return res.status(400).send('没有检测到上传文件。');
  }

  res.send({
    message: '文件上传成功!',
    fileName: req.file.filename,
    fileSize: req.file.size
  });
});

app.listen(3000, () => {
  console.log('服务器已启动:http://localhost:3000');
});

其中upload.single('avatar')告诉Multer查找名为avatar的表单字段,将文件保存到uploads/目录,并将文件对象附加到req.file

  1. 多文件上传

要同时上传多个文件,可以使用array方法(适用于同一字段名的多个文件)或fields方法(适用于不同字段名的文件)。

使用数组上传示例

// 最多接受5个名为"photos"的文件
app.post('/upload-multiple', upload.array('photos', 5), (req, res) => {
  if (!req.files || req.files.length === 0) {
    return res.status(400).send('没有文件被上传。');
  }

  res.send({
    message: `成功上传了${req.files.length}个文件!`,
    files: req.files.map(f => ({ name: f.filename, size: f.size }))
  });
});
  1. 存储配置

默认情况下,Multer会将文件保存到目标文件夹,并使用随机生成的难以辨认的文件名(这有助于防止文件名冲突和安全问题)。然而,在实际应用中通常需要更精细地控制保存的文件名和扩展名。

可以通过multer.diskStorage()来实现这一点。

自定义存储和文件名

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    // 指定文件保存的目录
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    // 使用时间戳和原始扩展名生成唯一文件名
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    const extension = file.originalname.split('.').pop();
    cb(null, file.fieldname + '-' + uniqueSuffix + '.' + extension);
  }
});

const uploadWithConfig = multer({ storage: storage });

app.post('/upload-custom', uploadWithConfig.single('avatar'), (req, res) => {
  res.send('文件已使用自定义配置上传!');
});
  1. 静态文件服务

保存到本地目录的文件不会自动可以通过Web访问。要在Express中提供静态文件服务,可以使用内置的express.static中间件。

server.js文件顶部附近添加以下代码,使uploads文件夹可公开访问:

app.use('/uploads', express.static('uploads'));

现在,如果文件被保存为uploads/avatar-12345.jpg,你可以通过浏览器访问http://localhost:3000/uploads/avatar-12345.jpg

总结

本文涵盖的内容:

  1. 为什么需要中间件: 解析包含二进制文件流的multipart/form-data格式。

  2. Multer配置: 使用简单目标文件夹或精细的磁盘存储。

  3. 处理上传: 处理单文件和多文件上传场景。

  4. 提供文件访问: 使用Express的static方法暴露本地存储。

掌握这些基础知识后,你已经能够很好地处理Express.js应用中的文件上传需求!

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。