VUE-API
插件
nodemon: 文件改动时重启服务器
express: 框架
multer: 用于处理 multipart/form-data 类型的表单数据
orm: 提供数据库操作
mysql: 连接 MySql 数据库
node-uuid: 生成 UUID
jsonwebtoken: 用于生成 JWT 字符串
express-jwt: 将 jwt 字符串进行解析还原为 JSON 对象
multer 文件上传
用于处理 multipart/form-data
类型的表单数据,它主要用于上传文件。
注意: Multer
不会处理任何非 multipart/form-data
类型的表单数据。
Multer
会添加一个 body
对象 以及 file
或 files
对象 到 express
的 request
对象中。 body
对象包含表单的文本域信息,file
或 files
对象包含对象表单上传的文件信息。
基本使用
const express = require("express");
const multer = require("multer");
const upload = multer({ dest: "uploads/" });
const app = express();
app.post("/profile", upload.single("avatar"), function (req, res, next) {
// req.file 是 `avatar` 文件的信息
// req.body 将具有文本域数据,如果存在的话
});
app.post(
"/photos/upload",
upload.array("photos", 12),
function (req, res, next) {
// req.files 是 `photos` 文件数组的信息
// req.body 将具有文本域数据,如果存在的话
}
);
const cpUpload = upload.fields([
{ name: "avatar", maxCount: 1 },
{ name: "gallery", maxCount: 8 },
]);
app.post("/cool-profile", cpUpload, function (req, res, next) {
// req.files 是一个对象 (String -> Array) 键是文件名,值是文件数组
//
// 例如:
// req.files['avatar'][0] -> File
// req.files['gallery'] -> Array
//
// req.body 将具有文本域数据,如果存在的话
});
如果你需要处理一个只有文本域的表单,你应当使用 .none()
:
const express = require("express");
const app = express();
const multer = require("multer");
const upload = multer();
app.post("/profile", upload.none(), function (req, res, next) {
// req.body 包含文本域
});
文件信息
Key | Description | Note |
---|---|---|
fieldname | Field name | 由表单指定 |
originalname | 用户计算机上的文件的名称 | |
encoding | 文件编码 | |
mimetype | 文件的 MIME 类型 | |
size | 文件大小(字节单位) | |
destination | 保存路径 DiskStorage | |
filename | 保存在 destination 中的文件名 | DiskStorage |
path | 已上传文件的完整路径 | DiskStorage |
buffer | 一个存放了整个文件的 Buffer | MemoryStorage |
API
multer(opts)
Multer 接受一个 options
对象,其中最基本的是 dest
属性,这将告诉 Multer 将上传文件保存在哪。如果你省略 options
对象,这些文件将保存在内存中,永远不会写入磁盘。
为了避免命名冲突,Multer 会修改上传的文件名。这个重命名功能可以根据您的需要定制。
以下是可以传递给 Multer 的选项。
Key | Description |
---|---|
dest or storage | 在哪里存储文件 |
fileFilter | 文件过滤器,控制哪些文件可以被接受 |
limits | 限制上传的数据 |
preservePath | 保存包含文件名的完整文件路径 |
dest or storage 存储
dest
const upload = multer({ dest: "uploads/" });
磁盘存储引擎 (DiskStorage)
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "/tmp/my-uploads");
},
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now());
},
});
const upload = multer({ storage: storage });
destination
是用来确定上传的文件应该存储在哪个文件夹中。也可以提供一个 string (例如 '/tmp/uploads'
)。如果没有设置 destination
,则使用操作系统默认的临时文件夹。
注意: 如果你提供的 destination
是一个函数,你需要负责创建文件夹。当提供一个字符串,multer
将确保这个文件夹是你创建的。
filename
用于确定文件夹中的文件名的确定。 如果没有设置 filename
,每个文件将设置为一个随机文件名,并且是没有扩展名的。
注意: Multer 不会为你添加任何扩展名,你的程序应该返回一个完整的文件名。
内存存储引擎 (MemoryStorage)
内存存储引擎将文件存储在内存中的 Buffer 对象,它没有任何选项。
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
当使用内存存储引擎,文件信息将包含一个 buffer 字段,里面包含了整个文件数据。
limits 文件限制
一个对象,指定一些数据大小的限制。
Key | Description | Default |
---|---|---|
fieldNameSize | field 名字最大长度 | 100 bytes |
fieldSize | field 值的最大长度 | 1MB |
fields | 非文件 field 的最大数量 | 无限 |
fileSize | 在 multipart 表单中,文件最大长度 (字节单位) | 无限 |
files | 在 multipart 表单中,文件最大数量 | 无限 |
parts | 在 multipart 表单中,part 传输的最大数量(fields + files) | 无限 |
headerPairs | 在 multipart 表单中,键值对最大组数 | 2000 |
fileFilter 文件过滤
设置一个函数来控制什么文件可以上传以及什么文件应该跳过
function fileFilter(req, file, cb) {
// 这个函数应该调用 `cb` 用boolean值来
// 指示是否应接受该文件
// 拒绝这个文件,使用`false`,像这样:
cb(null, false);
// 接受这个文件,使用`true`,像这样:
cb(null, true);
// 如果有问题,你可以总是这样发送一个错误:
cb(new Error("I don't have a clue!"));
}
.single(fieldname)
接受一个以 fieldname
命名的文件。这个文件的信息保存在 req.file
const multer = require("multer");
const upload = multer({ dest: "./public/data/uploads/" });
app.post("/stats", upload.single("uploaded_file"), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body);
});
.array(fieldname[, maxCount])
接受一个以 fieldname
命名的文件数组。可以配置 maxCount
来限制上传的最大数量。这些文件的信息保存在 req.files
。
const multer = require("multer");
const upload = multer({ dest: "./public/data/uploads/" });
app.post(
"/photos/upload",
upload.array("photos", 12),
function (req, res, next) {
// req.files 是 `photos` 文件数组的信息
// req.body 将具有文本域数据,如果存在的话
}
);
.fields(fields)
接受指定 fields
的混合文件。这些文件的信息保存在 req.files
。
.fields
应该是一个对象数组,应该具有 name
和可选的 maxCount
属性。
[
{ name: "avatar", maxCount: 1 },
{ name: "gallery", maxCount: 8 },
];
.none()
只接受文本域。如果任何文件上传到这个模式,将发生 “LIMIT_UNEXPECTED_FILE” 错误。这和 upload.fields([]) 的效果一样。
.any()
接受一切上传的文件。文件数组将保存在 req.files。
错误处理
const multer = require("multer");
const upload = multer().single("avatar");
app.post("/profile", function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// 发生错误
} else if (err) {
// 发生错误
}
// 一切都好
});
});
orm 提供数据库操作
// 初始化orm
const orm = require("orm");
app.use(
orm.express("mysql://test:123456@localhost:3306/test", {
define: function (db, modeld, next) {
next();
},
})
);
node-uuid: 生成 UUID
const uuid = require("node-uuid");
uuid.v4(); // 生成随机的UUID
jsonwebtoken、express-jwt: 接口增加 token 验证
配置中间件
const { expressjwt: expressJWT } = require("express-jwt");
// secret: 加密秘钥 algorithms: 加密算法
router.use(
expressJWT({ secret: "abcdefg", algorithms: ["HS256"] }).unless({
path: ["/user/login"], // 无需token验证的接口
})
);
router.use(function (err, req, res, next) {
// token解析失败
if (err.name === "UnauthorizedError") {
return res.status(401).json({
code: "20000",
msg: "token已失效",
});
}
res.status(401).json({
code: "20000",
msg: "未知错误",
});
next();
});
生成 token
const jwt = require("jsonwebtoken");
router.post("/user/login", function (req, res) {
const username = req.body.username;
const password = req.body.password;
if (username == "admin" && password == "123456") {
let payload = {
userName: "admin",
};
const secretKey = "abcdefg";
const options = {
expiresIn: "1h", // 过期时间1h
};
const token = jwt.sign(payload, secretKey, options);
return res.json({
code: "10000",
token: token,
});
} else {
res.json({
code: "20000",
message: "账号密码有误",
});
}
});
通过 token 获取用户信息
// 获取用户信息
router.post("/user/getUserInfo", function (req, res) {
res.json({
code: "10000",
data: {
userName: req.auth.userName, // admin
},
});
});