前言----------------------------------------
又是许久许久没有更新,在苦哈哈弄完期末,然后花一天时间把计算机网络课设写了之后。现在又即将回到前后端学习的状态。我想现在正处于一个调整期的状态。一个是随着 blog 的不断堆积,有必要把它们整理成更具有逻辑性的知识片。另一个是我需要了解当前前后端需要学习的路线,这样我可以有一个更明确地学习规划。言不在多,开始工作吧!
日程----------------------------------------
以后不能熬太多夜了,今天又是 9 点多起的床,这样太消耗身体了。今天早上的任务是整理 blog 的内容。又弄了一下午的课设,在我不懈努力之下,我终于是选择了放弃,麻了。
-----------6.23-------------
今天开始学 Nodejs,学了 buffer 和 fs 模块,来写写 blog
一放假早上就起不来了,得慢慢把时差调回来
晚上七点半了,把 http 模块学得差不多了,做做 blog
学习内容----------------------------------------
用于内存的分配,以下是常见的创建方式:
let buf = Buffer.alloc(10);
let buf_2 = Buffer.allocUnsafe(10);
let buf_3 = Buffer.from("hello");
let buf_4 = Buffer.from([85, 234, 231, 21, 85, 94]); console.log(buf_4[0].toString());
用于文件操作,以下是常见的操作:
const fs = require('fs');
fs.writeFile('./test.txt', 'test12356', err => { if (err == null) { console.log('写入成功'); } });
fs.writeFileSync('./test.txt', 'test2441');
fs.appendFile('./test.txt', ',not my test', err => {});
const ws = fs.createWriteStream('./test.txt', { flags: 'a' });
ws.write("\r\n我");
ws.write('\r\n是');
ws.write('\r\n谁?');
ws.end();
__dirname
可以获取当前的执行文件所在目录,通过 path
模块拼接路径:const path = require('path');
const filepath = path.join(__dirname, 'test.txt');
API | 说明 |
---|---|
path.resolve | 拼接规范的绝对路径 常用 |
path.sep | 获取操作系统的路径分隔符 |
path.parse | 解析路径并返回对象 |
path.basename | 获取路径的基础名称 |
path.dirname | 获取路径的目录名 |
path.extname | 获取路径的扩展名 |
fs.readFile(filepath, (err, data) => { console.log(data.toString()); });
const rs = fs.createReadStream(filepath);
rs.on('data', chunk => { console.log(chunk.toString()); });
ws = fs.createWriteStream(path.join(__dirname, 'test2.txt'));
rs.pipe(ws);
fs.rename(path.join(__dirname, 'test2.txt'), path.join(__dirname, 'test3.txt'), err => {});
fs.unlink(path.join(__dirname, 'test3.txt'), err => {});
rm
方法,两者的功能类似:fs.rm(path.join(__dirname, 'test3.txt'), err => {});
fs.mkdir(path.join(__dirname, 'dir1'), err => {});
fs.mkdir(path.join(__dirname, 'dir2/3/4/5'), { recursive: true }, err => {});
fs.readdir(__dirname, (err, data) => { console.log(data); });
fs.rmdir(path.join(__dirname, 'dir1'), err => {});
fs.rm(path.join(__dirname, 'dir2'), { recursive: true }, err => {});
fs.stat(__dirname + '/test.txt', (err, data) => {
console.log(data);
});
获取到的内容:Stats {
dev: 0,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 7318349395273121,
size: 49,
blocks: 0,
atimeMs: 1750658164362.0237,
mtimeMs: 1750652965429.8325,
ctimeMs: 1750656700147.115,
birthtimeMs: 1750652121205.9016
}
可以通过自定义输出来让内容更加格式化:fs.stat(__dirname + '/test.txt', (err, stats) => {
console.log('文件信息:', {
isFile: stats.isFile(), // 是否是文件
isDirectory: stats.isDirectory(), // 是否是目录
size: stats.size + ' bytes', // 文件大小
createdAt: stats.birthtime, // 创建时间(Date 对象)
modifiedAt: stats.mtime, // 修改时间(Date 对象)
accessedAt: stats.atime, // 访问时间(Date 对象)
});
});
结果如下:文件信息: {
isFile: true,
isDirectory: false,
size: '49 bytes',
createdAt: 2025-06-23T04:15:21.206Z,
modifiedAt: 2025-06-23T04:29:25.430Z,
accessedAt: 2025-06-23T05:56:04.362Z
}
通过 Nodejs 来控制 http 相关的请求和响应内容:
const http = require('http');
const server = http.createServer((req, rep) => {
//设置响应头 utf-8
rep.setHeader('content-type', 'text/html;charset=utf-8');
//设置响应体
rep.end('你好');
});
server.listen(9000, () => {
console.log('服务已经启动');
});
含义 | 语法 |
---|---|
请求方法 | request.method |
请求版本 | request.httpVersion |
请求路径 | request.url |
URL 路径 | require('url').parse(request.url).pathname |
URL 查询字符串 | require('url').parse(request.url, true).query |
请求头 | request.headers |
请求体 | request.on('data', function(chunk){}) request.on('end', function(){}); |
比较常用的是请求方法和请求路径。获取 url 路径: |
const server = http.createServer((req, rep) => {
...
//实例化 URL 对象
let url = new URL(req.url, 'http://127.0.0.1');
//输出路径
console.log(url.pathname);
//输出查询字符串
console.log(url.searchParams.get('key'));
...
});
假设现在访问 http://localhost:9000/heyi?key=124
,则控制台返回:/heyi
124
作用 | 语法 |
---|---|
设置响应状态码 | response.statusCode |
设置响应状态描述 | response.statusMessage |
设置响应头信息 | response.setHeader('头名', '头值') |
设置响应体 | response.write('xx') /> response.end('xxx') |
注意 response.end() 代表了响应处理的结束,会将响应结果返回给网页。一般设置内容用 response.write() 更加灵活一点,将 end 仅作为结尾。响应体是可以设置为一个文件 / 文件流的。通过设置响应体来加载 html 界面: |
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, rep) => {
let html = fs.readFileSync(__dirname + '/test.html');
rep.end(html);
});
server.listen(9000, () => {});
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="./test.css">
head>
<body>
<h1>你好 broh1>
<button index="btn1" class="style">点我button>
<script src="test.js">script>
body>
html>
首先我们手动加载了 html 资源,当浏览器发现 html 引用了 css,js 等资源时,它会向服务器发送对应的资源请求。如果是像我们之前那种写法,无论什么请求,都获取到了 html 资源,是肯定会出错的。我们需要动态的为资源请求进行相应请求体设置:const server = http.createServer((req, rep) => {
let { pathname } = new URL(req.url, 'http://127.0.0.1');
//拼接文件路径
if (req.url == '/') pathname = '/test.html';
let filePath = __dirname + pathname;
//异步读取资源
fs.readFile(filePath, (err, data) => {
if (err) {
rep.statusCode = 500;
rep.end('文件读取失败');
return;
}
rep.end(data);
});
});
形式 | 特点 |
---|---|
http://atguigu.com/web |
直接向目标资源发送请求,容易理解。网站的外链会用到此形式 |
//atguigu.com/web |
与页面 URL 的协议拼接形成完整 URL 再发送请求。大型网站用的比较多 |
/web |
与页面 URL 的协议、主机名、端口拼接形成完整 URL 再发送请求。中小型网站 |
http://www.atguigu.com/course/h5.html
:
形式 | 最终的 URL |
---|---|
./css/app.css |
http://www.atguigu.com/course/css/app.css |
js/app.js |
http://www.atguigu.com/course/js/app.js |
../img/logo.png |
http://www.atguigu.com/img/logo.png |
../../mp4/show.mp4 |
http://www.atguigu.com/mp4/show.mp4 |
MIME 类型结构 | 例子 |
---|---|
type/[subtype] | text/html, text/css, image/jpeg, image/png, application/json |
HTTP 服务可以设置响应头 Content-Type 来表明响应体的 MIME 类型,浏览器会根据该类型决定如何处理响应体。下面是常见文件对应的 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 |
基于这个,我们可以自己规范化设置 mine 值: |
const mines = {
html: 'text/html',
css: 'text/css',
js: 'text/javascript'
};
const server = http.createServer((req, rep) => {
let { pathname } = new URL(req.url, 'http://127.0.0.1');
//拼接文件路径
if (req.url == '/') pathname = '/test.html';
let filePath = __dirname + pathname;
//获取文件后缀名 //.txt -> txt
let ext = path.extname(filePath).slice(1);
//获取对应的类型
let type = mines[ext];
if (type) {
rep.setHeader('content-type', type + ';charset=utf-8');
} else {
rep.end('类型获取失败');
}
//异步读取资源
......
});
事实上,即使没有设置 mine,浏览器的嗅探机制也会根据返回的响应内容进行 mine 的设置。而中文字符集的设置,往往只需要设置 html 界面的,其他资源会基于 html 的字符集进行设置(尽管直接在网页读取资源时仍然是乱码):rep.setHeader('content-type', type + ';charset=utf-8');