Express 常见场景
记录使用 Express 作为后端服务器时的实用场景
文件上传
在 Express 应用程序中处理文件上传,可以使用 multer 中间件,它是一个用于处理文件上传的流行工具
使用 npm 安装 multer 模块
npm i multer在 express 中引入 multer 模块,配置文件上传的设置,例如:
const express = require('express')
const multer = require('multer')
const app = express()
// diskStorage: 将文件存储到本地磁盘
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, path.resolve(__dirname, 'public')) // 指定存储的目录
},
filename(req, file, cb) {
cb(null, file.originalname) // 指定上传文件的文件名
},
})
const upload = multer({ storage })创建一个路由来处理文件上传请求。在路由处理程序中使用upload.any()来处理单/多个文件上传。例如:
app.post('/upload', upload.any(), (req, res) => {
// req.files 包含上传的文件信息
// req.body 包含其他表单字段的数据
const result = req.files.map((f) => `/public/${f.filename}`)
res.json({ data: result }) // 使用json返回文件的访问路径的数组
})upload 中提供很多函数,用来处理不同场景的文件上传:
.single(fieldname):处理单文件上传;接受一个以fieldname命名的文件。这个文件的信息保存在req.file.array(fieldname[, maxCount]):处理多个文件上传;接受一个以fieldname命名的文件数组。可以配置maxCount来限制上传的最大数量。这些文件的信息保存在req.files。.fields(fields):处理多个文件上传;接受指定fields的混合文件。这些文件的信息保存在req.files。例如:js;[ { name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }, ].none():只接受文本域.any():接受一切上传的文件。文件数组将保存在req.files
在前端可以使用表单的方式进行文件上传,确保 enctype 属性设置为multipart/form-data,如:
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>还可以使用 AJAX 的方式,例如:
const fileInp = document.querySelector('input[type=file]')
const btn = document.querySelector('button')
// 文件上传
btn.addEventListener('click', function () {
// 构建form-data的消息体
const formData = new FormData()
for (const file of fileInp.files) {
formData.append('files', file)
}
fetch('/upload', {
body: formData,
method: 'POST',
})
.then((res) => res.json())
.then((res) => {
console.log(res)
})
})文件下载
可以使用 res.download()方法实现文件下载功能,例如:
const express = require('express')
const path = require('path')
const app = express()
// 客户端传递文件名,使用 res.download() 发送文件给客户端
app.get('/download/:filename', (req, res) => {
const filename = req.params.filename // 文件名
const filePath = path.resolve(__dirname, 'download', filename) // 文件路径
res.download(filePath, filename)
})上述示例中,我们创建了一个路由 /download/:filename,当客户端访问该路由时,传递要下载的文件名称,它将触发文件下载操作。res.download() 方法会自动设置适当的响应头,以便将文件提供给客户端进行下载
在前端可以使用 a 标签触发下载行为,例如:
<a href="localhost:3000/download/avatar.png" download></a>图片水印
要在 Express 中为图片添加水印,你可以使用一些 Node.js 的图像处理库,如 gm(GraphicsMagick)或 sharp。
使用 npm 安装 sharp 模块
npm i sharp然后,创建一个 Express 路由,用于处理图片并添加水印
const express = require('express')
const sharp = require('sharp')
const app = express()
// 中间件,用于处理图片并添加水印
app.get('/getimage', async (req, res) => {
try {
const imagePath = '/path/to/your/image.jpg' // 要处理的图片路径
const watermarkPath = '/path/to/your/watermark.png' // 水印图片路径
// 使用 sharp 打开要处理的图片
const image = sharp(imagePath)
// 使用 composite 方法添加水印
const watermarkedImage = await image.composite([
{
input: watermarkPath,
gravity: 'southeast', // 水印位置(可根据需要调整)
blend: 'over', // 混合模式
},
])
// 将处理后的图片输出到响应
watermarkedImage.toBuffer((err, data) => {
res.setHeader('Content-Type', 'image/jpeg') // 替换为实际图片类型
res.send(data)
})
} catch (error) {
console.error('Error:', error)
res.status(500).send('Internal Server Error')
}
})
app.listen(3000, () => {
console.log('Express应用正在监听3000端口。')
})上述示例中,将水印图片添加在原图片的右下角(southeast),效果如下:
| 原图 | 水印图 | 含水印(右下角) |
![]() | ![]() | ![]() |
客户端接收 express 发送的处理后的图片数据:
fetch('/getimage')
.then((res) => res.arrayBuffer())
.then((data) => {
// data 包含图像的二进制数据
const blob = new Blob([data], { type: 'image/jpeg' }) // 替换为实际的图像类型
const url = URL.createObjectURL(blob)
// 创建一个图片元素并设置其 src 属性
const img = document.createElement('img')
img.src = url
// 将图片元素添加到页面中的某个容器中
document.getElementById('image-container').appendChild(img)
})实际开发中,替换示例中的 /getimage 路径为实际服务器的路径,并根据图像的实际类型(例如,'image/jpeg'、'image/png' 等)调整 Blob 对象的类型
图片防盗链
图片防盗链(Image Hotlinking Protection)是一种网站安全措施,用于阻止其他网站或域名上的内容(通常是图片)在未经授权的情况下直接链接到自己的网站上。可能会导致以下问题:
- 带宽消耗:其它网站消耗你的服务器带宽,而你需要为带宽的消耗买单。
- 资源盗用:其它网站可能未经授权使用你的图片,这可能侵犯你的知识产权。
- 数据传输成本:如果你的网站受到大量盗链攻击,可能会导致不必要的数据传输成本
为了防止图片盗链,可以在服务器检查请求的 Referer 头部(请求头中的 Referer 字段表示请求的来源),如果请求的 Referer 不在白名单内,服务器可以拒绝提供图片。
编写一个 Express 中间件来防止图片盗链,检查请求的 Referer 头部,并与允许的域名进行比较。如果请求的 Referer 不在白名单内,可以发送适当的响应,例如返回 403 禁止访问或者重定向到其他页面。例如:
const express = require('express')
const app = express()
const port = 3000
// 允许访问的域名列表
const allowedDomains = ['http://example.com', 'https://example.net']
// 图片防盗链中间件
const preventHotlinking = (req, res, next) => {
const referer = req.get('Referer') // 获取客户端请求头的 Referer
if (referer && allowedDomains.every(d => !referer.includes(d))) {
// 如果 Referer 存在且不在白名单内,返回 403 禁止访问
return res.status(403).send('Forbidden')
}
// 否则,继续处理请求
next()
}
// 使用图片防盗链中间件
app.use('/images', preventHotlinking)
// 静态文件中间件,用于提供图片
app.use('/images', express.static('public/images'))
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})生成二维码
可以使用现有的第三方库,例如 qrcode,它支持浏览器端、NodeJS 使用
npm i qrcode在 express 中配置一个路由,使用 qrcode 将字符串内容转为二维码图片
const express = require('express')
const QRCode = require('QRCode')
const app = express()
app.get('/qrcode/:text', (req, res) => {
// 客户端提供的文字
const text = req.params.text
// 二维码的颜色
const color = { dark: '#000000', light: '#ffffff' }
// 将 text 生成二维码图片
QRCode.toFile('./code.png', text, color, function (err) {
if (err) throw err
console.log('QR Code generated!')
})
res.send('QR Code generated!')
})
app.listen(3000, () => {
console.log('Server started on port 3000')
})以上是 Express 的常见应用场景。



