《Node.js Express 实战:简易文件上传服务开发》
前言
在后端开发中,文件上传是非常高频的业务场景:头像上传、文档提交、图片素材管理等业务都离不开该能力。很多初学者一开始就直接上手云存储SDK,忽略本地文件上传底层逻辑。本文不引入复杂组件,使用 Express + multer 快速搭建一个基础文件上传服务,理解文件接收、校验、存储的完整流程。
注意:本项目为学习演示项目,生产环境需要增加更多安全策略,同时建议搭配对象存储服务,不要直接在服务器磁盘大量存放用户文件。
技术栈介绍
- Node.js:后端运行环境
- Express:轻量 Web 框架,快速搭建 HTTP 服务
- multer:Node.js 生态专门处理
multipart/form-data表单文件上传的中间件 - fs / path:Node.js 内置模块,用于文件路径处理与目录操作
项目初始化
新建项目文件夹,执行初始化命令:
# 初始化package.json
npm init -y
# 安装依赖
npm install express multer
在项目根目录创建 uploads 文件夹,用来存放上传后的文件。
完整代码 index.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const app = express();
const port = 3000;
// 配置上传存储规则
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
// 时间戳+原始文件名,防止重名覆盖
const uniqueName = Date.now() + '-' + file.originalname;
cb(null, uniqueName);
}
})
// 文件过滤:只允许图片类型
const fileFilter = (req, file, cb) => {
const allowTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (allowTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('仅支持 jpg/png/gif 图片上传'), false);
}
}
// multer实例:限制单文件最大5MB
const upload = multer({
storage: storage,
fileFilter: fileFilter,
limits: { fileSize: 5 * 1024 * 1024 }
})
// 单文件上传接口,字段名avatar
app.post('/upload', upload.single('avatar'), (req, res) => {
res.json({
code: 200,
msg: '上传成功',
data: {
filename: req.file.filename,
path: `/uploads/${req.file.filename}`,
size: req.file.size
}
})
})
// 获取上传文件列表接口
app.get('/file/list', (req, res) => {
fs.readdir('uploads', (err, files) => {
if(err) {
return res.json({code:500, msg:'读取目录失败'})
}
res.json({code:200, data: files})
})
})
// 静态资源访问,可直接访问上传图片
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
// 全局错误捕获
app.use((err, req, res, next) => {
res.json({code:400, msg: err.message})
})
app.listen(port, () => {
console.log(`服务启动成功,监听端口 ${port}`);
})
代码核心讲解
-
Storage 存储配置
diskStorage用来定义文件保存目录与文件名策略。这里使用时间戳拼接原始文件名,避免同名文件互相覆盖。真实业务中,还可以使用UUID生成文件名。 -
文件校验
fileFilter对文件 MIME 类型做校验,过滤非图片文件;limits设置文件大小上限,防止超大文件占用服务器存储与带宽,这是上传接口最基础的安全防护。很多线上漏洞就是因为缺少文件大小、类型校验,导致恶意文件上传。 -
接口说明
- POST
/upload:单文件上传接口,表单字段名称固定为avatar,上传成功返回文件信息; - GET
/file/list:读取uploads目录,返回已经上传的文件清单; express.static将上传目录暴露为静态资源,上传图片后可以直接通过url访问。
本地测试
启动服务:
node index.js
推荐使用 Postman / Apifox 测试:请求方式 POST,地址 [http://127.0.0.1:3000/upload](http://127.0.0.1:3000/upload),body选择form-data,key填写avatar,类型选择文件,选择一张图片提交。上传成功后,浏览器访问 [http://127.0.0.1:3000/uploads/xxx.jpg](http://127.0.0.1:3000/uploads/xxx.jpg) 即可查看图片。访问 /file/list 获取全部上传文件。
实战踩坑总结
- 目录不存在报错:multer不会自动创建uploads文件夹,必须手动新建,否则上传直接报错。生产代码可以加fs判断目录是否存在,不存在自动创建。
- 安全风险提醒
本示例仅用于学习。直接把用户文件存服务器磁盘存在风险:
- 不要允许上传
.js、.php等脚本文件,防止恶意代码执行; - 生产环境建议使用华为云对象存储OBS替代本地磁盘存储;
- 增加请求频率限流,防止大量请求刷满服务器存储。
生产优化方向
- 增加JWT鉴权,上传接口需要登录才能调用;
- 增加接口限流,使用
express-rate-limit; - 接入对象存储,文件直传OBS,服务器只负责业务逻辑;
- 增加文件删除接口;
- 数据库记录上传文件元信息,替代读取本地文件列表。
总结
文件上传是后端开发的基础能力,通过这个小型项目,我们掌握 multer 中间件使用、文件校验、静态资源托管等知识点。代码量不大,但覆盖了后端接收文件的完整流程。在学习完成之后,可以尝试将该项目部署到华为云ECS公网环境,对外提供上传测试服务,加深云服务器部署实践经验。
- 点赞
- 收藏
- 关注作者
评论(0)