Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框
有问题查看express官方文档:https://www.expressjs.com.cn/
使用的express版本:npm i [email protected]
创建一个最基本的express服务器
和nodejs中的http模块创建服务器一样
基本步骤: 引入模块 => 创建服务器 => 监听端口
var express = require("express"); // npm i express 安装express模块,然后require导入express
var server = express(); // 创建一个express http 服务器
server.listen(8899, function () {
console.log("服务启动:8899");
});
监听请求
get、post、put、delete都可以监听
server.get("/getReq", function (req, res) {
console.log("i got it");
res.send("hello");
});
server.post("/postReq", function (req, res) {
console.log("posted");
res.send("world");
});
server.put("/putReq", function (req, res) {
res.send("modify something");
});
server.delete("/delReq", function (req, res) {
res.send("deleted something");
});
托管静态文件
express.static(root, [options])
第一个参数是托管那个文件夹下的文件
第二个参数:
var options = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now())
}
}
server.use(express.static("public")); // public目录下所有的文件都作文静态文件托管
http://localhost:8899/bgc.jpg // 然后我们既可以直接可以访问到图片
router.js文件,给他单独放在一个模块
express.Router不能监听put和delete请求
const express = require("express"); // Router是express中的一个函数,所以要先引入express
const router = express.Router(); // 创建路由对象
router.get("/getReq", (req, res) => { // 将接口挂在到router上
res.send("hello,gt");
});
router.post("/postReq", (req, res) => {
res.send("hello,post");
});
module.exports = router; // 暴露路由对象
server.js文件
const router = require("./router.js");
const server = express();
// server.use(router);
server.use("/api", router); // 可以在所有路由前添加一个公共的baseUrl
server.listen(8888, () => {
console.log("服务启动成功:8888");
});
可以正则匹配,entry , try ,……
router.get(/.*try$/, function (req, res) {
res.send("reg");
});
1》处理请求
请求信息
req.headers: 获取请求头信息
处理 url 中的参数
req.query // 得到的是一个参数对象
处理 body 参数
借助中间件body-parser,这是自带的中间件,不需要npm i
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// req.body就可以拿到body中的参数了
2》处理响应
设置响应状态码:
res.status(code)
res.status(200).send('hello')
设置响应头:
res.set(name,value)
res.set('Content-Type', 'text/plain')
向客户端发送响应以及可选的状态码:res.send(body),res.send(stauts,body)
设置浏览器处理文件的方式:res.attachment([filename]),res.download(path,[filename],[callback]) 这俩方法会将响应报头Content-Disposition设置为attachment(Content-Disposition:inline是展示,attachment为下载),浏览器会选择下载而不是展现内容。此外你还要把要下载的内容发到客户端;
根据路径读取文件发到客户端:res.sendFile(path,[option],[callback])
设置响应内容
res.send([body])
body可以是 Buffer
object, String
, object, Boolean
, 或者 Array
设置content-type
响应一个文件
响应出去一个任意类型文件,也可以直接返回html文件做渲染
res.sendFile(path [, options][, fn])
他会根据文件的后缀设置响应的Content-Type;options中可以设置响应的headers等
基本语法
中间件实际上是函数,它有四个基本参数, err、req、res、next
(err,req,res,next) => {}
app.use(中间件函数) 定义一个全局生效的中间件(app是express http实例)
server.use((req,res,next)=>{
next();
});
分类
1》全局中间件
定义多个全局中间件,会按照定义顺序来执行
多个中间件之间,共享同一份 req
和 res
,因此可以在上游 的中间件中,统一为 req
或 res
对象添加自定义的属性和方法,供下游的中间件或路由进行使用
server.use((req, res, next) => { // 第一个中间件
req.moreInfo = "additionInfo";
next();
});
server.use((req, res, next) => { // 第二个中间件
console.log(req.moreInfo);
next();
});
2》局部的中间件
// 下面的中间件,只为当前接口 /test 这个接口服务
app.get('/test', 中间件函数);
// 下面的几个中间件,是处理 /api/hello 接口的,可以有多个中间件
app.post('/api/hello', 中间件函数, 中间件函数, 中间件函数, 中间件函数 .....);
路由中错误处理中间件(四个参数都要填,一般放到最后)
router.use((err, req, res, next) => {
// err 就是前面next过来的参数值
res.send({ status: 400, message: err });
});
注意事项
1》一定要在路由之前注册中间件
2》客户端发送过来的请求,可以连续调用多个中间件进行处理
3》执行完中间件的业务代码之后,不要忘记调用 next()
函数
4》为了防止代码逻辑混乱,调用 next()
函数后不要再写额外的代码
5》连续调用多个中间件时,多个中间件之间,共享 req
和 res
对象
使用跨域中间件处理跨域问题
// 导入 express 模块,并创建express http实例
const express = require("express");
const app = express();
// 导入中间件cors,先得npm i,他不是内置模块
const cors = require("cors");
// 配置中间件,这里是全局的一个中间件
app.use(cors());
// 导入路由模块,并注册到 app 上
const router = require("./router.js");
app.use("/api", router);
// 调用 app.listen 方法,指定端口号并启动 web 服务器
app.listen(9000, () => {
console.log("running……");
});
将self.pdf下载,并名命为test.pdf
1》方法1:利用iframe标签下载
router.get("/getStream", (req, res) => {
res.set("Content-Type", "application/octet-stream");
res.set("Content-Disposition", "attchment;filename=test.pdf");
const rs = fs.createReadStream("./self.pdf");
rs.on("data", function (data) {
res.status(200).send(data);
});
});
创建一个iframe标签,设置iframe的src属性来请求文件流,Content-Disposition设置默认下载并取好文件名
downPdf() {
const IFRAME = document.createElement("iframe");
IFRAME.style.display = "none";
IFRAME.style.height = 0;
// src 就是请求服务地址自行修改。
IFRAME.src = `http://localhost:8080/api/getStream`;
document.body.appendChild(IFRAME);
setTimeout(() => {
IFRAME.remove();
}, 60 * 1000);
},
方法2:利用a标签下载
router.get("/getStream", (req, res) => {
res.set("Content-Type", "application/octet-stream");
res.set("Content-Disposition", "inline");
const rs = fs.createReadStream("./self.pdf");
rs.on("data", function (data) {
res.status(200).send(data);
});
});
一定要设置responseType:blob 或arraybuffer,不然下载打开是空白(这是个坑)
dealClick() {
axios
.get("/api/getStream", {
responseType: "blob",
})
.then((res) => {
let blob = new Blob([res.data], {
type: "application/pdf;charset-UTF-8",
});
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.download = "gogo.pdf";
a.style.display = "none";
a.href = blobUrl;
a.click();
URL.revokeObjectURL(blobUrl);
});
},