【翻译】使用node.js和express实现简单的文件上传服务
原文链接:https://attacomsian.com/blog/uploading-files-nodejs-express
大量移动应用和网站允许用户上传账号头像等文件。因此,使用 Node.js 和 express 处理文件上传是一个很常见的 REST API 开发场景。在这个教程中,我们将讨论如何使用 Node.js 和 express 处理单个、多个文件上传,并且将上传的文件保存到服务器的指定位置。
初始化
首先,通过运行以下命令创建一个新的 node.js app。我使用的是 npm,你也可以根据喜好使用 yarn。
# 创建一个新的目录并进入
$ mkdir files-upload && cd files-upload
# 创建新的 app
$ npm init -y
# 或者使用 yarn 创建新的 app
$ yarn init -y
-y 或 --yes 跳过了交互步骤并根据你的默认信息创建 package.json。下一步,运行以下命令安装需要的依赖:
# npm运行以下命令
$ npm install express body-parser cors express-fileupload morgan lodash --save
# 或者使用yarn
$ yarn add express body-parser cors express-fileupload morgan lodash
以下是各组件的功能简述:
express- Node.js 上流行的 web 框架。我们将使用它来开发 REST API。body-parser- Node.js 请求 body 解析器,可在你的 handler 之前解析传入的请求体,并且使其可通过 req.body 属性访问。简而言之,简化传入的请求。cors- 另一个 Express 中间件,用于启用 CORS 跨域请求。express-fileupload- 用于上传文件的简单的 Express 中间件。它可以解析multipart/form-data请求, 如果有文件的话会提取文件并且使其可通过req.files属性访问。morgan- 用于记录HTTP请求日志的 Node.js 中间件。lodash- 一个提供数组、数字、对象、字符的工具函数的 JavaScript 库。
创建 Express 服务器
安装完需要的依赖项后,我们开始创建 Express 服务器。
index.js
const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const _ = require('lodash');
const app = express();
// 启用文件上传
app.use(fileUpload({
createParentPath: true
}));
//添加其他中间件
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan('dev'));
//启动app
const port = process.env.PORT || 3000;
app.listen(port, () =>
console.log(`App is listening on port ${port}.`)
);
上述代码应该还是比较好理解的。首先它设置了 express-fileupload 中间件来支持 multipart/form-data 请求. 然后, 其他 Express 被添加来允许跨域 (CORS), 请求体解析, 以及 HTTP 请求日志。最后,它在端口3000启动服务器。
上传单个文件
我们来创建我们的第一条路由,来允许用户上传他们的账户头像。
app.post('/upload-avatar', async (req, res) => {
try {
if(!req.files) {
res.send({
status: false,
message: 'No file uploaded'
});
} else {
//Use the name of the input field (i.e. "avatar") to retrieve the uploaded file
let avatar = req.files.avatar;
//Use the mv() method to place the file in upload directory (i.e. "uploads")
avatar.mv('./uploads/' + avatar.name);
//send response
res.send({
status: true,
message: 'File is uploaded',
data: {
name: avatar.name,
mimetype: avatar.mimetype,
size: avatar.size
}
});
}
} catch (err) {
res.status(500).send(err);
}
});
以上代码片段是一个 HTTP POST 方法。当你发送一个 multipart/form-data 请求到 /upload-avatar 路由来上传一个文件,这个方法将文件存储到服务器的 uploads 文件夹。
express-fileupload 中间件原理?
它使得上传的文件可以通过 req.files 属性访问到。例如如果你上传的文件名为 my-profile.jpg, 然后你的field name是 avatar, 你可以通过 req.files.avatar 访问到该文件。此 avatar 对象包括以下信息:
avatar.name- 上传的文件名,如my-profile.jpgavatar.mv- 此方法将文件移到服务器的其他路径avatar.mimetype- 文件的 mime-typeavatar.size- bytes单位的文件大小avatar.data- 文件的buffer呈现
上传多个文件
我们来创建另一个路由来允许用户一次上传多个照片。
app.post('/upload-photos', async (req, res) => {
try {
if(!req.files) {
res.send({
status: false,
message: 'No file uploaded'
});
} else {
let data = [];
//遍历所有文件
_.forEach(_.keysIn(req.files.photos), (key) => {
let photo = req.files.photos[key];
//将照片移动到指定文件夹
photo.mv('./uploads/' + photo.name);
//将文件信息写入data数组
data.push({
name: photo.name,
mimetype: photo.mimetype,
size: photo.size
});
});
//返回response
res.send({
status: true,
message: 'Files are uploaded',
data: data
});
}
} catch (err) {
res.status(500).send(err);
}
});
以上代码和单个文件上传很相似,除了我们现在收到的 field 是 photos 而不是 avatar。我们使用 lodash 下的 forEach() 和 keysIn()方法遍历 photos 并且将所有文件存入 uploads 目录下。
测试服务
大功告成!在终端项目根目录下,输入以下命令来启动应用:
$ node index.js
应用将在端口 3000 启动。我们将使用 postman 来发送 multipart/form-data 请求:
1. 单个文件

2. 多个文件

如果你想要让上传的文件能够被外界访问,只需要把 uploads 作为静态目录:
app.use(express.static('uploads'));
至此,你可以直接在浏览器中打开上传的文件:
http://localhost:3000/icon.png
限制文件大小
如果你想要限制一次上传的文件的总大小,将 limits 选项传入 express-fileupload 中间件:
app.use(fileUpload({
createParentPath: true,
limits: {
fileSize: 2 * 1024 * 1024 * 1024 //文件总大小上限2MB
},
}));
源代码:https://github.com/attacomsian/code-examples/tree/master/nodejs/files-upload(MIT协议)
结论
以上就是我们如何使用 node.js 和 express 搭建一个简单的单文件/多文件上传服务! express-fileupload 是一个非常易用的处理文件上传的中间件。你也可以查看其文档来了解更多设置选项。
浙公网安备 33010602011771号