目录
[2.1 写入文件](#2.1 写入文件)
[2.1.1 writeFile写入](#2.1.1 writeFile写入)
[2.1.2 追加写入](#2.1.2 追加写入)
[2.1.3 流式写入](#2.1.3 流式写入)
[2.2 读取文件](#2.2 读取文件)
[2.2.1 readFile读取](#2.2.1 readFile读取)
[2.2.2 流式读取](#2.2.2 流式读取)
[2.3 文件复制](#2.3 文件复制)
[2.4 文件重命名和移动](#2.4 文件重命名和移动)
[2.5 文件删除](#2.5 文件删除)
[2.6 文件夹操作](#2.6 文件夹操作)
[2.7 查看资源状态](#2.7 查看资源状态)
[2.8 路径](#2.8 路径)
[2.9 批量重命名](#2.9 批量重命名)
[2.10 path模块](#2.10 path模块)
[3.1 HTTP协议](#3.1 HTTP协议)
[3.2 HTTP](#3.2 HTTP)
[3.2.1 创建HTTP服务端](#3.2.1 创建HTTP服务端)
[3.2.2 获取HTTP请求报文](#3.2.2 获取HTTP请求报文)
[3.2.3 设置HTTP响应报文](#3.2.3 设置HTTP响应报文)
[3.3 网页资源加载基本过程](#3.3 网页资源加载基本过程)
[3.4 网页中的URL](#3.4 网页中的URL)
[3.4.1 绝对路径(项目中常用)](#3.4.1 绝对路径(项目中常用))
[3.4.2 相对路径(学习中常用,不安全)](#3.4.2 相对路径(学习中常用,不安全))
[3.5 设置资源类型(mime类型)](#3.5 设置资源类型(mime类型))
[3.6 get和post请求应用场景和区别](#3.6 get和post请求应用场景和区别)
注意:nodejs中不能使用DOM和BOM,顶级对象是global,globalThis指向顶级对象
1、Buffer
一段固定长度的内存空间,用来处理二进制数据
特点:Buffer 大小固定且无法调整 、性能较好,可以直接对计算机内存进行操作 、每个元素的大小为 1 字节(byte)
Buffer的创建
javascript
// alloc
// let buf = Buffer.alloc(10); // 创建一个10字节的Buffer
// console.log(buf) // 把每一位归零
// allocUnsafe
// let buf = Buffer.allocUnsafe(10);
// console.log(buf) // 不归零,比alloc快,但是不安全,内存可以复用,可能有之前程序遗留的数据
// from
// let buf = Buffer.from('hello'); //Unicode码表完全兼容ASCll码表
// let buf1 = Buffer.from([105, 108, 111, 108, 101, 121, 111, 117])
// console.log(buf1)
Buffer的操作
javascript
// buffer与字符串的转换
let buf1 = Buffer.from([105, 108, 111, 108, 101, 121, 111, 117])
// console.log(buf1.toString()) // 默认采用utf-8 编码方式
buf1[0] = 97
// console.log(buf1.toString())
// buffer元素的读写
let buf = Buffer.from('hello')
// console.log(buf[0]); // 获取第一个元素 得到的是十进制的数字
// console.log(buf[0].toString(2)) // 转换成二进制
// 溢出
// let buf2 = Buffer.from('hello')
// buf2[0] = 361 // 8个二进制位265<361 361:0001 0110 1001 => 高于8位,会舍弃高位的数字:0110 1001
// console.log(buf2)
// 中文
let buf2 = Buffer.from('你好') // utf-8的字符,一个字符占3个字节
console.log(buf2)
2、fs模块
2.1 写入文件
场景:下载文件、安装软件、保存程序日志eg:Git、编辑器保存文件、视频录制...
当需要持久化的保存数据时,我们应该想到写入文件
2.1.1 writeFile写入
javascript
// 1. 导入fs模块
const fs = require('fs')
// writeFile(file文件名, data写入文件的内容, option(可选), callback) 返回值:void
// writeFile 异步写入
fs.writeFile('./111.txt', '111', err => {
// err成功;null 失败:错误对象
if (err) {
console.log('失败')
return
}
console.log('成功')
})
// writeFileSync 同步写入
fs.writeFileSync('./222.txt', '222')
2.1.2 追加写入
javascript
// appendFile(file文件名, data写入文件的内容, option(可选), callback) 返回值:undefined
fs.appendFile('./111.txt', '23456', err => {
if (err) {
console.log('失败')
return
}
console.log('成功')
})
// appendFileSync 异步追加写入 返回值:undefined
fs.appendFileSync('./222.txt','3456')
// \r\n 换行
fs.appendFileSync('./222.txt','\r\n3456')
// writeFile 实现追加写入
fs.writeFile('./111.txt', '111', { flag: 'a' }, err => {
// err成功;null 失败:错误对象
if (err) {
console.log('失败')
return
}
console.log('成功')
})
应用场景:需要持续的往文件中写内容,eg:日志
2.1.3 流式写入
javascript
// 1. 导入fs模块
const fs = require('fs')
// 创建写入流对象
let ws = fs.createWriteStream('./ws.txt')
ws.write('11111\r\n')
ws.write('22222\r\n')
ws.write('33333\r\n')
// 关闭通道
ws.end()
当脚本执行完毕后,资源会回收,通道会被断开,内容已经写入完毕,因此end加不加都可
流式写入适用于大文件写入或者频繁写入;writeFile适合于写入频率较低的场景
2.2 读取文件
场景:电脑开机、程序运行、编辑器打开文件、查看图片、播放视频、播放音乐、Git查看日志、上传文件、查看聊天记录
2.2.1 readFile读取
javascript
// 1. 导入fs模块
const fs = require('fs')
// readFile(path, option(可选),callback)
fs.readFile('./111.txt', (err, data) => {
if (err) {
console.log('失败')
return
}
console.log(data.toString())
})
2.2.2 流式读取
javascript
// 1. 导入fs模块
const fs = require('fs')
// 创建读取流对象
let rs = fs.createReadStream('./111.txt')
// 绑定 data 事件 一块一块的读,当从文件中读一块就调用一次回调
rs.on('data', chunk => {
console.log(chunk)
console.log(chunk.length)
// 如果是一个视频文件,toString得不到想要的结果
console.log(chunk.toString())
})
rs.on('end', () => {
console.log('读取完成');
})
2.3 文件复制
javascript
// 1. 导入fs模块
const fs = require('fs')
const process = require('process')
// 方式一 readFile 把所有的文件读取到内存中,再写入文件
let data = fs.readFileSync('./111.txt')
fs.writeFileSync('./222.txt', data)
// 获取程序的内存占用量
console.log(process.memoryUsage())
// 方式二 流式操作 更好,一块一块的读取,但是读取的速度比写入的速度快
const rs = fs.createReadStream('./111.txt')
const ws = fs.createWriteStream('./333.txt')
// rs.on('data', chunk => {
// ws.write(chunk)
// })
// rs.on('end', () => {
// console.log(process.memoryUsage())
// })
// 快速复制
rs.pipe(ws)
2.4 文件重命名和移动
javascript
// 1. 导入fs模块
const fs = require('fs')
// 重命名
// rename(old path,new path,callback) renameSync 同步
fs.rename('./111.txt', './555.txt', err => {
if (err) {
console.log('失败')
return
}
console.log('成功')
})
// 文件的移动
fs.rename('./222.txt', '../test/222.txt', err => {
if (err) {
console.log('失败')
return
}
console.log('成功')
})
2.5 文件删除
javascript
// 1. 导入fs模块
const fs = require('fs')
// 方式一:unlink 同步:unlinkSync
// fs.unlink('./555.txt', err => {
// if (err) {
// console.log('失败')
// return
// }
// console.log('成功')
// })
// 方式二:rm 同步:rmSync
fs.rm('./ws.txt', err => {
if (err) {
console.log('失败')
return
}
console.log('成功')
})
2.6 文件夹操作
javascript
// 1. 导入fs模块
const fs = require('fs')
// 创建文件夹
// // mkdir(path(,option),callback)
// fs.mkdir('./html/', err => {
// if (err) {
// console.log('失败')
// return
// }
// console.log('成功')
// })
// // 递归创建
// fs.mkdir('./a/b/c', { recursive: true }, err => {
// if (err) {
// console.log('失败')
// return
// }
// console.log('成功')
// })
// // 读取文件夹
// fs.readdir('../test', { recursive: true }, (err, data) => {
// if (err) {
// console.log('失败')
// return
// }
// console.log(data)
// })
// 删除文件夹
// fs.rmdir('./html', err => {
// if (err) {
// console.log('失败')
// return
// }
// console.log('成功')
// })
// 递归删除
// 不建议使用
// fs.rmdir('./a', { recursive: true }, err => {
// if (err) {
// console.log('失败')
// return
// }
// console.log('成功')
// })
// 建议使用
fs.rm('./a', { recursive: true }, err => {
if (err) {
console.log('失败')
return
}
console.log('成功')
})
2.7 查看资源状态
javascript
// 1. 导入fs模块
const fs = require('fs')
fs.stat('../test/222.txt', (err, data) => {
if (err) {
console.log('失败')
return
}
console.log(data)
})
2.8 路径
javascript
// 1. 导入fs模块
const fs = require('fs')
const path = require('path')
// 相对路径
fs.writeFileSync('./index.html', '111')
fs.writeFileSync('/index.html', '111')
fs.writeFileSync('../index.html', '111')
// 绝对路径 C盘不可以,因为没有权限
fs.writeFileSync('D:/index.html','111')
// 相对路径参照物:命令行的工作目录
// __dirname:保存的是所在文件的所在目录的绝对路径
console.log(__dirname)
fs.writeFileSync(__dirname + 'D:/index.html', '111')
2.9 批量重命名
javascript
// 1. 导入fs模块
const fs = require('fs')
const files = fs.readdirSync('./test')
console.log(files)
files.forEach(item => {
let data = item.split('-')
let [num, name] = data
if (num < 10) {
num = '0' + num
}
let newName = num + '-' + name
fs.renameSync(`./test${item}`, `./test/${newName}`)
})
2.10 path模块

javascript
const path=require('path')
// resolve(绝对路径, 相对路径)
path.resolve(__dirname, './index.html')
path.resolve(__dirname, 'index.html')
// sep 分隔符 当前操作系统的路径分隔符
console.log(path.sep)
console.log(__filename) // 文件的绝对路径
let str = 'D:\\Nodejs\\index.html'
// console.log(path.parse(str))
// console.log(path.basename(str))
// console.log(path.dirname(str))
// console.log(path.extname(str))
3、HTTP模块
IP的作用:标识网络中的设备,实现设备间通信
端口的作用:实现不同主机访问相同应用
HTTP服务在哪个文件夹中寻找静态资源,哪个文件夹就叫静态资源目录,也就是网站根目录
3.1 HTTP协议
HTTP协议:请求行+请求头+空行+请求体
请求行:请求方法+请求的URL+HTTP的版本号
请求方法:GET:用于获取数据 POST:用于新增数据
PUT/PATCH:更新数据 DELET:删除数据
URL:统一资源定位符
URL:协议名+ :// +主机名(+端口号)+路径(+查询字符串(键值对))
请求头:由一系列的键值对组成,主要记录浏览器的相关信息、交互的行为、请求体相关的信息
请求体:和查询字符串格式一样
响应报文:响应行+响应头+空行+响应体
响应头:HTTP版本号+响应状态码+响应状态的描述
记录与服务器相关的信息和响应体相关的信息
响应状态码

响应状态描述

响应体常见格式:HTML、CSS、JavaScript、图片、视频、JSON
3.2 HTTP
响应内容解决中文乱码问题:
javascriptresponse.setHeader('content-type', 'text/html;charset=utf-8')HTTP协议默认端口是80。HTTP服务开发常用端口有3000,8080,8090,9000等
HTTPS协议默认端口是443。可以使用资源监视器查看端口占用情况
3.2.1 创建HTTP服务端
javascript
// 1. 导入http模块
const http = require('http')
// 2. 创建服务对象
// 第一个参数是封装请求报文的对象
// 第二个参数是封装响应报文的对象
// 回调函数执行时机:当服务接收到http请求时
const server = http.createServer((request, Response) => {
Response.end('Hello HTTP') // 设置响应体,并结束这个响应
})
// 3. 监听端口,启动服务
// 回调函数执行时机:当服务启动成功时
// 浏览器可以发送HTTP请求 9000端口
// 本机(回环地址):127.0.0.1
server.listen(9000, () => {
console.log('Server Success')
})
3.2.2 获取HTTP请求报文

- 获取请求行和请求头
javascript
// 1. 导入http模块
const http = require('http')
const server = http.createServer((request, response) => {
response.setHeader('content-type', 'text/html;charset=utf-8')
console.log(request.method)
console.log(request.url) //只包含 url 中的路径和查询字符串
console.log(request.httpVersion) //获取http协议的版本号
console.log(request.headers) //获取请求头
console.log(request.headers.host) //获取端口号
response.end('HTTP')
})
server.listen(9000, () => {
console.log('Server Success')
})
- 获取请求体(这个方法了解即可)
javascript
// 1. 导入http模块
const http = require('http')
const server = http.createServer((request, response) => {
let body = ''
request.on('data', chunk => {
console.log(chunk)
body += chunk
})
request.on('end', () => {
console.log(body)
response.end('hello Http')
})
})
server.listen(9000, () => {
console.log('Server Success')
})
- 获取请求路径和查询字符串
方式一:
javascript// 1. 导入http模块 const http = require('http') const url = require('url') const server = http.createServer((request, response) => { // console.log(request.url) // let res = url.parse(request.url) let pathname = url.parse(request.url).pathname let query = url.parse(request.url, true).query.keyword console.log(pathname) console.log(query) response.end('url') }) server.listen(9000, () => { console.log('Server Success') })方式二:
javascript// 1. 导入http模块 const http = require('http') const server = http.createServer((request, response) => { // 实例化 URL 的对象 // let url = new URL('http://www.xxx.com/s?a=100&b=10') // let url = new URL('/s?a=100&b=10', 'http://127.0.0.1:9000') let url = new URL(request.url, 'http://127.0.0.1:9000') // console.log(url) console.log(url.pathname) // url.search是一个字符串,我们用起来不方便 // searchParams是一个对象 使用get方法获取 console.log(url.searchParams.get('keyword')) response.end('url') }) server.listen(9000, () => { console.log('Server Success') })
3.2.3 设置HTTP响应报文

javascript
const http = require('http')
const server = http.createServer((request, response) => {
// 设置响应状态码
response.statusCode = 200
// 响应状态的描述
response.statusMessage = 'success'
// 响应头
response.setHeader('content-type', 'text/html;charset=utf-8')
// response.setHeader('myHeader', 'test test')
// 设置多个同名响应头
// response.setHeader('test', ['a', 'b', 'c'])
// 响应体 一般使用write时,最后在end中就不设置响应体了,write可以多次复用设置响应体
response.write('response')
response.write('response')
response.write('response')
response.write('response')
response.end()
// response.end('end...')
})
server.listen(9000, () => {
console.log('Server Success')
})
3.3 网页资源加载基本过程

首先发送http请求,获取网页的html内容,当看到link标签引入的css文件时,发送http请求获取css内容,浏览器使用css中的样式去控制页面当中的元素样式,在html中遇到img标签,需要呈现一个外部的图片资源,向服务器发送请求,在html中遇到script标签,有src属性时,继续向服务器发送请求,获取js资源,完成整个页面的加载。(发送请求是一个异步的过程,并不是发一个请求,等待响应之后才发下一个请求)
3.4 网页中的URL
两类:相对路径和绝对路径
3.4.1 绝对路径(项目中常用)

3.4.2 相对路径(学习中常用,不安全)
相对路径发送请求时,需要与当前页面URL路径进行计算,得到完整的URL后,再发送请求
eg:当前网页url为:http://www.atguigu.com/course/h5.html

3.5 设置资源类型(mime类型)
媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 )是一种标准,用来表示文档、文件或字节流的性质和格式。
mime 类型结构: [type]/[subType]
例如: text/html text/css image/jpeg image/png application/json
HTTP 服务可以设置响应头 Content-Type 来表明响应体的 MIME 类型,浏览器会根据该类型决定如何处理资源
下面是常见文件对应的 mime 类型:
html : 'text/html' ,
css : 'text/css' ,
js : 'text/javascript' ,
png : 'image/png' ,
jpg : 'image/jpeg' ,
gif : 'image/gif' ,
mp4 : 'video/mp4' ,
mp3 : 'audio/mpeg' ,
json : 'application/json'
对于未知的资源类型,可以选择 application/octet - stream 类型,浏览器在遇到该类型的响应
时,会对响应体内容进行独立存储,也就是我们常见的 下载 效果
javascript
const http = require('http')
const fs = require('fs')
const path = require('path')
const mimes = {
html: 'text/html',
css: 'text/css',
js: 'text/javascript',
png: 'image/png',
jpg: 'image/jpeg',
gif: 'image/gif',
mp4: 'video/mp4',
mp3: 'audio/mpeg',
json: 'application/json'
}
const server = http.createServer((request, response) => {
let { pathname } = new URL(request.url, 'http://127.0.0.1')
let root = __dirname + '/page'
let filePath = root + pathname
fs.readFile(filePath, (err, data) => {
if (err) {
response.setHeader('content-type', 'text/html;charset=utf-8')
response.statusCode = 500
response.end('no success')
return;
}
// 获取文件的后缀名
let ext = path.extname(filePath).slice(1)
// console.log(ext)
let type = mimes[ext]
if (type) {
// 解决乱码问题 比html中的meta优先级高
response.setHeader('content-type', type + ';charset=utf-8')
} else {
response.setHeader('content-type', 'application/octet-stream')
}
response.end(data)
})
})
server.listen('9000', () => {
console.log('serve')
})
3.6 get和post请求应用场景和区别
GET 请求的情况:
- 在地址栏直接输入 url 访问
- 点击 a 链接
- link 标签引入 css
- script 标签引入 js
- img 标签引入图片
- form 标签中的 method 为 get (不区分大小写)
- ajax 中的 get 请求
POST 请求的情况:
- form 标签中的 method 为 post(不区分大小写)
- AJAX 的 post 请求
区别:
- 作用:GET 主要用来获取数据,POST 主要用来提交数据
- 参数位置:GET 带参数请求是将参数缀到 URL 之后,在地址栏中输入 url 访问网站就是 GET 请求,POST 带参数请求是将参数放到请求体中
- 安全性:POST 请求相对 GET 安全一些,因为在浏览器中参数会暴露在地址栏
- GET 请求大小有限制,一般为 2K,而 POST 请求则没有大小限制