koa
陆波
# koa
# 安装
npm i koa
# 使用
# 创建服务器
const koa = require("koa");
const app = new koa();
app.use((ctx, next) => {
console.log(1);
ctx.body = "hello";
next();
});
app.use((ctx, next) => {
console.log(2);
ctx.body += " world";
});
app.listen(8080);
# api 中间件
const koa = require("koa");
const app = new koa();
app.use((ctx, next) => {
// console.log(ctx);
// let name = 'jack'
// ctx.state.name = name
// ctx.throw(404, '出错了', {a: 1})
console.log(ctx.request);
next();
});
app.use((ctx, next) => {
// throw new Error();
// console.log(ctx.state.name);
ctx.response.body = { name: "jack" };
});
app.on("error", (err) => {
console.log(err);
});
app.listen(8080);
# koa-static-cache
npm i koa-static-cache
const path = require("path");
const koa = require("koa");
const koaStaticCache = require("koa-static-cache");
const app = new koa();
app.use(
koaStaticCache(path.join(__dirname, "static"), {
prefix: "/public",
})
);
app.use(
koaStaticCache(path.join(__dirname, "static/img"), {
prefix: "/img",
})
);
app.use((ctx, next) => {
ctx.body = "hello";
});
app.listen(8088);
# koa-router
npm koa-router
const koa = require("koa");
const koaRouter = require("koa-router");
const app = new koa();
const router = new koaRouter();
// app.use((ctx, next) => {
// console.log(ctx.URL);
// ctx.body = 'hello'
// })
// router.get('/user', (ctx, next) => {
// ctx.body = 'user-get';
// })
// 路由嵌套 方式一
const userRouter = new koaRouter();
userRouter.get("/", (ctx, next) => {
ctx.body = "user-get";
});
userRouter.get("/info", (ctx, next) => {
ctx.body = "user-info";
});
router.use("/user", userRouter.routes());
// 路由嵌套 方式二
const indexRouter = new koaRouter({
prefix: "/index",
});
indexRouter.get("/", (ctx, next) => {
ctx.body = "index-get";
});
indexRouter.get("/add", (ctx, next) => {
ctx.body = "index/add-get";
});
// 动态路由
const dynamicRouter = new koaRouter();
dynamicRouter.get("/dynamic/:id", (ctx, next) => {
ctx.body = `dynamic - ${ctx.params.id}`;
});
router.get("/", (ctx, next) => {
ctx.body = "首页";
});
app.use(router.routes());
app.use(indexRouter.routes());
app.use(dynamicRouter.routes());
app.listen(8088, "localhost");
# koa-bodyparser
npm i koa-bodyparser
const koa = require("koa");
const Router = require("koa-router");
const bodyParser = require("koa-bodyparser");
const app = new koa();
app.use(bodyParser());
const router = new Router();
router.get("/", async (ctx) => {
ctx.body = "hello";
});
router.post("/change", (ctx) => {
let { id, name, price, number } = ctx.request.body;
console.log({ id, name, price, number });
});
app.use(router.routes());
app.listen(8088);
# koa-swig
npm i koa-swig co
const koa = require("koa");
const koaRouter = require("koa-router");
const Swig = require("koa-swig");
const co = require("co");
const render = Swig({
root: __dirname + "/view", // 模板存放目录
autoescape: true, // 是否自动escape编码
cache: false, // 是否启用缓存,开发时可以不启用,线上使用 'memory'
ext: ".html", // 模板后缀
});
const app = new koa();
const router = new koaRouter();
app.context.render = co.wrap(render);
let users = [{ username: "张三" }, { username: "李四" }, { username: "王五" }];
router.get("/", (ctx, next) => {
ctx.body = "home";
});
router.get("/user", (ctx, next) => {
ctx.body = `<!DOCTYPE html>
<html lang="en">
<head>
<title>模板文件</title>
</head>
<body>
<h1>koa swig</h1>
</body>
</html>`;
});
router.get("/list", async (ctx, next) => {
ctx.body = await ctx.render("1.html", { users });
});
app.use(router.routes());
app.listen(8088);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>koa swig</h1>
<p>list-{{Math.random()}}</p>
<ul>
{% for user in users %}
<li>{{user.username}}</li>
{% endfor %}
</ul>
</body>
</html>
# mysql2
npm i mysql2
(async () => {
const mysql = require("mysql2/promise");
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
database: "test",
});
const [rows, fields] = await connection.query("SELECT * FROM todolist");
console.log(rows);
})();
使用预处理语句
// insert
// const [result] = await connection.query(`INSERT INTO mytable (name, age) VALUES(${name}, ${age})`);
// update
const [result] = await connection.query("UPDATE `todolist` SET `name` = ? , `age` = ? WHERE `id` = ? ", [
name,
age,
id,
]);
// delete
const [result] = await connection.query(`DELETE FROM todolist WHERE id = ?`, id);
if (result.affectedRows > 0) {
// 操作成功
} else {
// 操作失败
}
注意:表名与列名不能使用占位符!
参数标记只能用于数据值应该出现的地方,不能用于 SQL 关键字、标识符等。
Parameter markers can be used only where data values should appear, not for SQL keywords, identifiers, and so forth.
13.5.1 PREPARE Statement (opens new window)
MySQL 中的某些对象,包括数据库、表、索引、列、别名、视图、存储过程、分区、表空间、资源组和其他对象名称,称为标识符。
Certain objects within MySQL, including database, table, index, column, alias, view, stored procedure, partition, tablespace, resource group and other object names are known as identifiers.
# koa-body
npm i koa-body
const Koa = require("koa");
const { koaBody } = require("koa-body");
const app = new Koa();
app.use(koaBody());
app.use((ctx) => {
ctx.body = `Request Body: ${JSON.stringify(ctx.request.body)}`;
});
app.listen(3000);
# 使用 koa-body 上传文件
文件上传 1
自定义存放文件夹、文件名称与支持多文件上传
// app.js或者自己的路由文件
const fs = require("fs");
const path = require("path");
const koaBody = require("koa-body"); // npm i koa-body
const { format } = require("date-fns"); // npm i date-fns
// POST@/upload
router.post(
"/upload",
koaBody({
multipart: true, // 支持多文件上传
encoding: "gzip", // 编码格式
formidable: {
uploadDir: path.join(__dirname, "/public/upload/"), // 设置文件上传目录
keepExtensions: true, // 保持文件的后缀
maxFieldsSize: 10 * 1024 * 1024, // 文件上传大小限制
onFileBegin: (name, file) => {
// 无论是多文件还是单文件上传都会重复调用此函数
// 最终要保存到的文件夹目录
const dirName = format(new Date(), "yyyyMMddhhmmss");
const dir = path.join(__dirname, `public/upload/${dirName}`);
// 检查文件夹是否存在如果不存在则新建文件夹
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
// 文件名称去掉特殊字符但保留原始文件名称
const fileName = file.name.replaceAll(" ", "_").replace(/[`~!@#$%^&*()|\-=?;:'",<>\{\}\\\/]/gi, "_");
file.name = fileName;
// 覆盖文件存放的完整路径(保留原始名称)
file.path = `${dir}/${fileName}`;
},
onError: (error) => {
app.status = 400;
log4js.error(error);
// 这里可以定义自己的返回内容
app.body = { code: 400, msg: "上传失败", data: {} };
return;
},
},
}),
async (ctx) => {
try {
// 获取上传文件
const files = ctx.request.files;
// 正则 替换掉文件原始路径中不需要的部分
const reg = new RegExp(".*/upload/", "g");
for (const fileKey in files) {
ctx.uploadpaths = ctx.uploadpaths ? ctx.uploadpaths : [];
ctx.uploadpaths.push({
name: files[fileKey].name,
url: files[fileKey].path.replace(reg, ""),
});
}
ctx.body = { code: 200, msg: "", data: { uploadpaths: ctx.uploadpaths } };
} catch (error) {
ctx.status = 400;
ctx.body = { code: 400, msg: "上传失败", data: {} };
}
}
);
文件上传 2
router.post(
"/upload",
koaBody({
multipart: true, // 支持多文件上传
encoding: "gzip",
formidable: {
maxFieldsSize: 10 * 1024 * 1024, // 文件上传大小限制
keepExtensions: true, // 保持文件的后缀
},
}),
async (ctx) => {
let { name, type } = ctx.request.body;
// 获取上传文件
const files = ctx.request.files;
// console.log(files);
for (let fileKey in files) {
const file = files[fileKey];
// 根据文件地址创建文件输入流
const fileReader = fs.createReadStream(file.filepath);
// 定义文件存储路径
let fileDir = path.join(__dirname, "static/img/");
// 判断路径是否存在
if (!fs.existsSync(fileDir)) {
fs.mkdirSync(fileDir);
}
let filepath = path.join(fileDir, name);
if (fs.existsSync(filepath)) {
let ext = path.extname(name),
realname = path.basename(name, ext),
newName = realname + "(1)" + ext;
filepath = path.join(fileDir, newName);
}
// 创建文件输出流
const fileWrite = fs.createWriteStream(filepath);
// 写入文件数据
fileReader.pipe(fileWrite);
}
ctx.body = {
code: 0,
msg: "上传成功",
url: "/upload" + name,
};
}
);