Nodejs - 01:Buffer、fs模块、HTTP模块

目录

1、Buffer

Buffer的创建

Buffer的操作

2、fs模块

[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、HTTP模块

[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

响应内容解决中文乱码问题:

javascript 复制代码
response.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 请求则没有大小限制
相关推荐
大漠_w3cpluscom2 小时前
为什么 :is(::before, ::after) 不能工作?
前端
aXin_li2 小时前
从原子化到工程化:Tailwind CSS 的深层价值与实践思考
前端·css
IT_陈寒2 小时前
用Python爬虫抓了100万条数据后,我总结了这5个反封禁技巧
前端·人工智能·后端
qq_411262422 小时前
AP模式中修改下wifi名称就无法连接了,分析一下
java·前端·spring
BUG创建者2 小时前
uniapp 开发app时播放实时视频海康ws的流数据
前端·javascript·vue.js·uni-app·html·音视频
我是苏苏2 小时前
Web开发:使用MediatR包实现中介者模式,避免组件之间直接通信
前端·中介者模式
wind5202 小时前
差分包技术
开发语言·node.js·安装·web app·openclaw·龙虾
Highcharts.js2 小时前
数据可视化不仅属于金融、互联网|农业数据可视化设计:Farmable与Highcharts的前端设计
前端·信息可视化·数据可视化·highcharts·农业可视化
JuneXcy2 小时前
node(2)
开发语言·前端·javascript·http·node.js