1. fs模块
1.1 读写和追加文件内容
const fs = require('fs')// 读取文件内容
fs.readFile('./a.txt', 'utf8', (err, data) => {console.log(err);console.log(data);
})// 写入文件内容
fs.writeFile('./a.txt', 'aaaaaaa', (e) => {console.log(e);
})// 读取文件夹
const files = fs.readdirSync('books')// 追加文件内容// 第一种
fs.appendFile('./a.txt', '我是要追加的内容', err => {console.log(err)
})// 第二种(a是追加append, w是写入write, r是读read, 默认是w)
fs.writeFile('./a.txt', '我要追加在尾部', {flag: 'a'}, (err) => {console.log(err);
})// 第三种
fs.readFile('./a.txt', 'utf8', (e, data) => {if (!e) {const newData = `${data}???`;fs.writeFile('./a.txt', newData, e => {if (!e) {console.log('追加内容成功啦');}})}
})
1.2 文化流式读取与写入
// 文件流式读取
const fs = require('fs')// 创建读取流对象
const rs = fs.createReadStream('./file.mp4')// 绑定data事件
rs.on('data', chunk => {console.log(chunk); // chunk.length 65536字节 => 64kb
})rs.on('end', () => {console.log('读取完成');
})// 文件流式写入
const fs = require('fs')const ws = fs.createWriteStream('./text.txt')ws.write('第1段内容')
ws.write('第2段内容')
ws.write('第3段内容')
ws.write('第4段内容')wx.close(); // 关闭通道
1.3 练习: 文件复制
// 复制文件
const fs = require('fs')
const process = require('process')// 第一种方式, 占用内存空间大
// const res = fs.readFileSync('./aaa.jpg')
// fs.writeFileSync('./bbb.jpg', res)// console.log(process.memoryUsage()); // rss 32546816字节// 第二种方式, 占用内存空间小
// const rs = fs.createReadStream('./aaa.jpg')
// const ws = fs.createWriteStream('./ccc.jpg')// rs.on('data', (chunk) => {
// ws.write(chunk)
// })// rs.on('end', () => {
// console.log(process.memoryUsage()); // rss
// })// 第三种方式, 占用内存空间最小
const rs = fs.createReadStream('./aaa.jpg')
const ws = fs.createWriteStream('./ccc.jpg')rs.pipe(ws)console.log(process.memoryUsage()); // rss
1.4 文件重命名和文件移动操作
const fs = require('fs')// 第一个参数是要操作文件的路径, 第二个参数是修改完文件路径后的名称和未知, 第三个是修改完毕后的回调函数// 文件重命名
// fs.rename('./aaa.jpg', './aaa1.jpg', err => {
// if (err) {
// return console.log(err);
// }
// console.log('成功');
// })// 文件移动(cs文件夹要创建否则会报错)
fs.rename('./aaa1.jpg', './cs/aaa.jpg', err => {if (err) {return console.log(err);} console.log('成功');
})
1.5 文件删除
const fs = require('fs')// 文件删除(unlink和rm都能删除, 其中rm是node14.4版本后新加的属性)// fs.unlink('./cs/ccc.jpg', err => {
// if (err) {
// return console.log('删除失败')
// }// console.log('删除成功');// })fs.rm('./ccc copy.jpg', err => {if (err) {return console.log('删除失败')}console.log('删除成功');})
1.6 文件夹操作(创建,读取和删除)
const fs = require('fs')// 文件夹操作
// 第一个参数是文件夹路径, 第二个参数选项配置, 第三个参数是操作后的回调
// 单个创建文件夹
// fs.mkdir('./html', err => {
// if (err) {
// return console.log('创建失败');
// }
// console.log('创建成功');
// })// 递归创建文件夹
// fs.mkdir('./a/b/c', {recursive: true}, err => {
// if (err) {
// return console.log('创建失败');
// }
// console.log('创建成功');
// })// 读取文件夹
fs.readdir('./html', (err, data) => {if (err) {return console.log('失败');}console.log(data, '成功');
})// 递归删除文件夹, 即文件夹非空(fs.rmdir也可以删除, 但不推荐, 以后的版本可能删除)
fs.rm('./a', {recursive: true}, err => {if (err) {return console.log('失败')}console.log('成功');})
1.7 查看资源状态以及判断该资源是文件夹还是文件
const fs = require('fs')// 查看资源状态
fs.stat('./aaa.jpg', (err, data) => {if (err) return console.log(err);// 该资源是否是文件console.log(data.isFile());// 该资源是否是文件夹console.log(data.isDirectory());})
1.8 练习, 批量重命名文件名字, 往前面数字加0
const fs = require('fs')// 练习, 批量重命名文件名字, 往前面数字加0
const files = fs.readdirSync(__dirname, '/code');files.forEach(item => {// 拆分文件名let [num, name] = item.split('-')if (Number(num) < 10) {num = `0${num}`}const newName = `${num}${name}`fs.renameSync(`./code/${item}`, `./code/${newName}`)
})
2. path模块
2.1 获取文件后缀名
// 获取文件后缀名
const path = require('path')const filePath = __dirname + '/login.ico'const ext = path.extname(filePath)console.log(ext) // .ico
3. http模块
3.1 请求体练习
// 路径是/login, 响应体返回登录页面, 路径是/register, 返回注册页面, 其余返回Not Found
const http = require('http')const server = http.createServer((request, response) => {// 设置响应头为utf-8否则中文会乱码response.setHeader('content-type', 'text/html;charset=utf-8')const {method} = request;// URL可以只传一个参数(如http://www.baidu.com/search?a=1&b=2)// 也可以传两个参数, 如下方案例, 如果使用/search?a=1&b=2这种路径, 那么第二个参数必须传域名否则会报错const {pathname} = new URL(request.url, 'http://127.0.0.1');if (method === 'GET' && pathname === '/login') {response.end('登录页面')} else if (method === 'GET' && pathname === '/register') {response.end('注册页面')} else {response.end('Not Found')}
})server.listen(9000, () => {console.log('启动成功');
})
3.2 实现网页引入外部资源+mime+解决乱码问题+完善错误处理
// 实现网页引入外部资源
// const http = require('http')
// const fs = require('fs')// const server = http.createServer((request, response) => {
// const {pathname} = new URL(request.url, '127.0.0.1')
// if (pathname === '/') {
// const html = fs.readFileSync(__dirname + '/index.html')
// response.end(html)
// } else if (pathname === '/index.css') {
// const css = fs.readFileSync(__dirname + '/index.css')
// response.end(css)
// } else if (pathname === '/index.js') {
// const js = fs.readFileSync(__dirname + '/index.js')
// response.end(js)
// } else {
// response.statusCode = 404
// response.end('<h1>404 Not Found</h1>')
// }
// })// server.listen(9000, () => {
// console.log('启动成功');
// })// 优化: 实现网页引入外部资源
// 设置mime类型
// 对于未知的资源类型, 可以选择application/octet-stream类型,浏览器在遇到该类型的响应时,会对响应体内容进行独立存储,也就是我们常见的下载效果
const mimes = {html: 'text/html',css: 'text/css',js: 'text/js',png: 'text/png',jpeg: 'text/jpeg',gif: 'text/gif',mp3: 'text/mp3',mp4: 'text/mp4',json: 'application/json',
}// 优化: 实现网页引入外部资源
const http = require('http')
const fs = require('fs')
const path = require('path')const server = http.createServer((request, response) => {// 只能发送GET请求if (request.method !== 'GET') {response.statusCode = 405;response.end('<h1>405 Method Not Allowed</h1>')}const {pathname} = new URL(request.url, '127.0.0.1')const filePath = __dirname + pathname;fs.readFile(filePath, (err, data) => {if (err) {switch (err.code) {case 'ENOENT':response.statusCode = 404response.end('<h1>404 Not Found</h1>')break;case 'EPERM':response.statusCode = 403response.end('<h1>403 Forbidden</h1>')break;default:response.statusCode = 500response.end('<h1>Internal Server Error</h1>')break;}return;}const ext = path.extname(filePath).slice(1) // path.extname(filePath)的结果是.css这种包含点的所以要去掉const type = mimes[ext];if (type) {// response.setHeader('content-type', type) // 比如结果是text/html, 它没加;charset=utf-8所以会乱码// 如果是html文件, 添加charset=utf-8if (ext === 'html') {response.setHeader('content-type', `${type};charset=utf-8`) // 解决乱码问题} else {response.setHeader('content-type', type)}} else {response.setHeader('content-type', 'application/octet-stream')}// 响应文件内容response.end(data)})
})server.listen(9000, () => {console.log('启动成功');
})
4. express
4.1 获取请求报文参数
const express = require('express')const app = express();app.get('/', (req, res) => {// 原生操作console.log(req.method)console.log(req.url)console.log(req.httpVersion)console.log(req.headers)// express 的操作console.log(req.path)console.log(req.query)// 获取ipconsole.log(req.ip)// 获取请求头console.log(req.get('host'))
})app.listen(9000, () => {console.log('启动成功')
})
4.2 练习: 路由参数获取
// 浏览器输入 http:127.0.0.1:9000/1.html 页面返回 {"id":1}
// 浏览器输入 http:127.0.0.1:9000/2.html 页面返回 {"id":2}
// 浏览器输入 http:127.0.0.1:9000/3.html 页面返回 404 not foundconst express = require('express')
const {list} = require('./data.json')const app = express();app.get('/:id.html', (req, res) => {// 浏览器输入 http:127.0.0.1:9000/1.html 后获取路由参数const {id} = req.params;console.log(list);const result = list.find(item => item.id == id);if (result) {res.end(JSON.stringify(result))} else {res.end('404 not found')}
})app.listen(9000, () => {console.log('启动成功')
})
5. MongoDB & mongoose
5.1 mongoose的使用
// mongoose的使用
// npm i mongooseconst mongoose = require('mongoose')// 连接mongodb服务
mongoose.connect('mongodb://127.0.0.1:27017/bilibili')// 设置相关回调// 成功回调 (官方建议使用once而不是on)
mongoose.connection.once('open', () => {console.log('连接成功');})// 失败回调
mongoose.connection.on('error', () => {console.log('连接失败');})// 关闭回调
mongoose.connection.on('close', () => {console.log('连接关闭');})setTimeout(() => {mongoose.disconnect();
}, 2000);
5.2 对文档进行增删改查、个性化读取、数据排序、数据读取、文档字段类型、内置字段值验证
// 插入文档const mongoose = require('mongoose')
mongoose.connect('mongodb://127.0.0.1:27017/bilibili')mongoose.connection.once('open', () => {console.log('连接成功');// 创建文档的结构对象, 设置集合中文档的属性以及属性值的类型const BookSchema = new mongoose.Schema({name: String,age: Number,ids: Number,add: String})// 创建模型对象, 对文档操作的封装对象// mongoose.model() 第一个参数是集合名词, 第二个参数是结构对象const BookModel = mongoose.model('books', BookSchema);// 新增// BookModel.create({// name: '你猜',// age: 444,// ids: 333,// add: 'ttt'// }).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// 删除单条和多条数据// BookModel.deleteOne({// name: '吴承恩'// }).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// BookModel.deleteMany({// name: '吴承恩'// }).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// 更新单条文档和多条文档// BookModel.updateOne({name: '吴承恩'}, {name: '吴承恩1'}).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// BookModel.updateMany({name: '吴承恩1'}, {name: '吴承恩'}).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// 读取单条和多条文档// BookModel.findOne({name: '吴承恩'}).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// BookModel.find({name: '吴承恩'}).then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err)// })// 设置返回字段, 查询到的数据只返回name和age, 其它不返回, _id设置后才能不显示, 值设置成1就行// BookModel.find().select({name: 1, age: 1, _id: 0}).exec().then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err);// })// 数据排序, 1表示正序(升序), 2是倒序// BookModel.find().sort({age: 1}).exec().then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err);// })// 数据的截取, 比如截取前三名// BookModel.find().select({name: 1, age: 1, _id: 0}).sort({age: 1}).limit(3).exec().then((data) => {// console.log(data, 'data');// }).catch((err) => {// if (err) return console.log(err);// })// 截取4 5 6名BookModel.find().select({name: 1, age: 1, _id: 0}).sort({age: 1}).skip(3).limit(3).exec().then((data) => {console.log(data, 'data');}).catch((err) => {if (err) return console.log(err);})
})// 内置字段值验证
const BookSchema = new mongoose.Schema({name: {type: String,required: true, // 设置必填项default: '默认值', // 设置默认值enum: ['男', '女'], // 设置枚举值, 只能输入设置的这几个值之一unique: true // 设置为独一无二的值, 必须重建集合才可以, 集合内的数据只能有一个值},
})//文档字段类型
// String 字符串
// Number 数字
// Boolean 布尔值
// Array 数组 也可以使用[]来标识
// Date 日期
// Buffer Buffer对象
// Mixed 任意类型,需要使用mongoose.Schema.Types.Mixed指定
// ObjectId 对象ID,需要使用mongoose.Schema.Types.ObjectId指定
// Decimal128 高精度数字,需要使用mongoose.Schema.Types.Decimal128指定
5.3 文档条件控制
// 文档条件控制// 1. 运算符
// 在mongodb不能使用><!==等运算符, 需要使用替代符号
> 使用 $gt
< 使用 $lt
>= 使用 $gte
<= 使用 $lte
!= 使用 $ne
比如db.students.find({id: {$gt: 3}}) // 获取id比3大的所有记录// 2. 逻辑运算
$or逻辑或的情况
db.student.find({$or: [{age: 18}, {age: 24}]}) // 查询年龄是18或者24的数据$and逻辑与的情况
db.student.find({$and: [{age: {$lt: 20}}, {age: {$gt: 15}}]}) // 查询年龄大于15且小于20的数据// 3. 正则匹配
db.students.find({name: /书籍/}) // 搜索名称含有书籍的数据
db.students.find({name: new RegExp('书籍')}) // 搜索名称含有书籍的数据