一台电脑可以部署多个服务器,根据端口不同找到不同的服务器。
默认的http端口为80端口。
静态服务器的流程
浏览器向服务器发起请求
服务器查询受否存在这个文件
存在
返回
不存在
返回默认404页面
静态服务器的实现
静态服务器实现与读取网页返回几乎一致,通过request.url可以获取用户访问的路径。
const http = require("http"); const fs = require("fs"); const path = require("path"); const server = http.createServer((req, res) => { // 得到用户请求的是哪一个页面 console.log(req.url); // /pica.jpg var filePath = path.join(__dirname, "static", req.url); // 服务器存在嗅探功能,根据请求资源名字,能够得知请求类型。因此编码参数可以省略 fs.readFile(filePath, (err, data) => { if (err == null) { res.end(data); } else { res.end(path.join(__dirname, "static", "404.html")); } }); }); server.listen(8080, () => { console.log("成功开启:http://127.0.0.1:8080"); });[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zrXbeRfG-1593759415691)(https://cdn.jsdelivr.net/gh/blogimg/HexoStaticFile2@latest/2020/07/02/89c40aaacb09a8adf0eafa16cec4c9b5.png)]
get参数是与url拼接在一起的,因此可以使用url.parse方法解析字符串。
const http = require("http"); // 处理url const url = require("url"); const server = http.createServer((req, res) => { // res.end(req.url); /** * url.parse 解析通过get传来的参数 * @param {string} req.url 待解析的url * @param {boolean} true 如果为true则返回一个对象 * @returns {Object} */ let urlObj = url.parse(req.url, true); console.log(urlObj.query); res.end(JSON.stringify(urlObj.query)); }); server.listen(8080, () => { console.log("成功开启"); });接收post数据需要为请求体注册data事件与end事件。前者表示接收数据,回调函数内参数传入数据,函数体处理数据;后者表示接收完数据后调用的回调函数。
处理接收的数据使用querystring.parse可以将接收的数据转换为对象形式。
const http = require("http"); const querystring = require("querystring"); const server = http.createServer((req, res) => { let postData = ""; // 时间处理程序,参数是传递过来的数据 req.on("data", (chunk) => { postData += chunk; }); req.on("end", () => { console.log(postData); //name=123&passwd=haha // 解析传来的参数数据 let postObj = querystring.parse(postData); //{ name: '123', passwd: 'haha' } console.log(postObj); }); res.end("sb"); }); server.listen(8080, () => { console.log("成功开启"); });使用第三方模块的步骤:
新建一个文件夹(非中文且不能与模块名相同)
npm init -y 进行初始化
下载模块
可以到npm官网搜索
使用模块
参照模块说明文档
爬取丁香园的body数据
const fs = require("fs"); var Crawler = require("crawler"); var c = new Crawler({ maxConnections: 10, callback: function (err, res, done) { if (err) { console.log(err); } else { var $ = res.$; fs.writeFile("./temp/1.txt", $("body").text(), (err) => { if (err == null) { console.log("成功"); } }); } done(); }, }); c.queue("https://ncov.dxy.cn/ncovh5/view/pneumonia");爬取一张图片
var Crawler = require("crawler"); var fs = require("fs"); var c = new Crawler({ encoding: null, jQuery: false, // set false to suppress warning message. callback: function (err, res, done) { if (err) { console.error(err.stack); } else { fs.createWriteStream(res.options.filename).write(res.body); } done(); }, }); c.queue({ uri: "https://ae01.alicdn.com/kf/H21b5f6b8496141a1979a33666e1074d9x.jpg", filename: "./temp/test.jpg", });安装当前目录下的项目所需要的所有依赖包npm install
如果下载过程中卡住,可以使用npm cache clean -f清除缓存
使用淘宝镜像
参考地址:https://developer.aliyun.com/mirror/NPM?from=tnpm
使用npm5之前的版本,是不会生成package-lock.json这个文件的。
npm5以后,包括npm5这个版本,才会生成package-lock.json文件
当使用npm安装包的时候,npm都会生成或書更新package-lock.json文件
npm5以后的版本,在安装包的时候,不需要加--save(s)参数,也会自动在package.json中保存依项当安装包的时候,会自动创建或更新package-jock.json文件package-lock.json文件内保存了node_modules:中所有包的信息,包含这些包的名称、版本号、下地址。带来好处是,如果重新npm install的时候,就无逐个分析包的依赖项,因比会大大加快安装速度从package-lock.json文件名来看,Iock代表的是"锁定"的意思。它用来物定当前开发使用的版本号,防止npm install的时侯自动更新到了更新版本。因为新版本有可能会更新老的API,导数之前的代码出错原来的package.json文件只能定大版本,也就是版本号的第一位,并不能定后面的小版本,你每次npm install都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几手是不敢随意升级依包的,这将导数多出来很多工作量,测试/适配等,所以package-lock.json文件出来了,当你每次安装一个依赖的候就定在你安装的这个版本。GET与POST传参:
GET传参–接收参数
只需要在请求体内直接通过request.query即可取到传参对象
POST参数–接收参数
需要导入body-parser模块,首先对url进行转码,然后在请求体内可以通过request.body获取传参对象
创建静态资源可以设置静态目录app.use(express.static("PATH"));
const express = require("express"); // 创建服务器 const app = express(); // 设置静态目录 app.use(express.static("static")); // 创建路由 app.get("/", (req, res) => { // 注意 使用express模块创建服务器,使用send作为相应 res.send("Hello World!你好啊"); }); // 监听接口 app.listen(3000, () => { console.log(`Server running at http://127.0.0.1:3000`); });返回json直接返回一个对象即可。
const express = require("express"); const app = express(); app.get("/food", (req, res) => { let arr = ["第一个笑话", "第二个笑话", "第三个笑话"]; let index = Math.floor(Math.random() * 3); res.send({ foodName: arr[index], price: 100, desc: "这是一个描述", }); }); app.listen(3000);通过req.query可以获取传输的参数对象,然后取到具体的内容。
const express = require("express"); const app = express(); app.get("/getNickName", (req, res) => { // 接收参数 let heroName = req.query.heroName; console.log(heroName); let heroNickName = ""; let hero = { 提莫: "迅捷斥候", 李青: "盲僧", 盖伦: "德玛西亚之力", 亚索: "疾风剑豪", }; if (hero[heroName] != undefined) { heroNickName = hero[heroName]; } else { heroNickName = "暂无这个英雄的资料"; } res.send(heroNickName); }); app.listen(3000);在post请求中,无法使用req.query拿到请求的数据。所以拿到数据需要使用第三方模块body-parser模块。
将请求体解析
app.use(bodyParser.urlencoded({ exrtended: false }));
通过req.body拿到请求的数据
const express = require("express"); const bodyParser = require("body-parser"); const app = express(); // 将请求体的数据解析 app.use(bodyParser.urlencoded({ exrtended: false })); app.post("/login", (req, res) => { console.log(req.body); if (req.body.name == "123" && req.body.passwd == "123") { res.send("登录成功"); } else { res.send("登录失败"); } }); app.listen(3000);使用express模块返回字符串默认为text/html格式,设置响应头后即可返回json格式的字符串。
const express = require("express"); const app = express(); app.get("/getFood", (req, res) => { res.setHeader("Content-Type", "text/json"); res.send( `foodName:"红烧肉", price:100` ); }); app.listen(3000, () => { console.log("服务器已开启"); });post接收文件参数需要使用multer模块,然后将传过来的文件放在此模块创建的文件夹下。
请求第二个可选参数为接收文件的键值。通过req.file获取文件信息,通过req.body获取一同传输的文本信息。
const express = require("express"); const multer = require("multer"); const app = express(); // 创建一个uploads文件夹 var upload = multer({ dest: "uploads/" }); app.post("/register", upload.single("usericon"), (req, res) => { // 传过来的文件,参数名用usericon // 一起传过来的文本信息保存在req.body中 console.log(req.file); console.log(req.body); res.send("sb"); }); app.listen(3000);