一、fs 模块

内置模块(built-in):node 的安装时已经内置了核心模块,不用我们制造,可以直接使用;

fs模块:file system 文件系统,文件读写模块,用于读写文件;

  1. let fs = require('fs');

1. 异步读取文件

  1. fs.readFile(fileName, option, callback)
  • fileName: 文件名
  • option: 以哪一种编码返回内容,默认的 buffer 类型的值,buffer 中存储的是二进制数据;所以一般设置为 utf8
  • callback: 读取文件后执行的回调
  1. fs.readFile('./text.txt', 'utf8', function (err, data) {
  2. err // 读取失败的错误信息
  3. data // 从文件中读取来的数据
  4. console.log(data)
  5. });

2. 同步读取文件

  1. fs.readFileSync(fileName, options);
  • fileName: 文件名
  • options: 编码
  • 该方法会返回同步读取到的内容
  1. let content = fs.readFileSync('./text.txt', 'utf8');
  2. console.log(content);

3. 异步写入(向文件中写)

  1. fs.writeFile(path, data, option, callback)
  • path 文件名(如果没有就创建一个文件)
  • data 写入文件的数据
  • option 文件编码
  • callback 写入后执行的回调
  1. fs.writeFile('1.js', 'console.log(`hello world`);','utf8', function (err, data) {
  2. if (err) {
  3. console.log(err);
  4. } else {
  5. console.log('写入成功')
  6. }
  7. });

4. 同步写入(向文件中写)

  1. fs.writeFileSync(path, data, option)
  • path 文件名及路径
  • data 写入的数据
  • option 写入的编码
  1. fs.writeFileSync('../x.js', 'alert(`hello world`)', 'utf8');

注意以上写入都是覆盖的写入,把文件中原有的内容覆盖掉;
**

5. 异步追加内容

  1. fs.appendFile(path, data, option, callback);
  • data 写入文件的数据
  • option 文件编码
  • callback 写入后执行的回调
  1. fs.appendFile('./1.js', '\nfunction sum (a, b) {return a + b}', 'utf8', function (err, data) {
  2. if (err) {
  3. console.log(err);
  4. } else {
  5. console.log(data)
  6. }
  7. });

6. 同步追加内容

  1. fs.appendFileSync(path, data, option);
  • path 文件名及路径
  • data 写入的数据
  • option 写入的编码
  1. fs.appendFileSync('../x.js', ';\n\rfunction minus(a, b) {return a - b}', 'utf8');

例子

  1. // fs 模块:是 Node.js 内置的模块;fs (file system 文件系统) 用于文件读写;
  2. let fs = require('fs');
  3. // 1. 异步读取文件:
  4. // __dirname 当前文件所处的路径,绝对路径
  5. // __filename 当前文件的带绝对路径的文件名,并且带扩展名
  6. // fs.readFile(带路径的文件名, 编码, callback)
  7. fs.readFile('./1.txt', 'utf8', (err, data) => {
  8. // 如果读取成功 err 是 null,如果读取失败 err 是对象;
  9. // 如果文件读取成功,会把读到的数据传给 data,在回调函数中使用这个 data 就是使用读取来的数据;
  10. if (err) {
  11. // console.log(err);
  12. // no such file or directory 没有这样一个文件或者文件夹;(导致报错的原因就是文件路径错误)
  13. } else {
  14. // console.log(data);
  15. }
  16. });
  17. // 2. 同步读取文件:
  18. // fs.readFileSync(带路径的文件名, 编码)
  19. // 返回值是读取到内容;
  20. // let data = fs.readFileSync('./1.txt', 'utf8');
  21. // console.log(data);
  22. // 修改文件:向文件中写入内容
  23. // 3. 异步写入文件
  24. // fs.writeFile(path, data, option, callback);
  25. // path 文件名(如果没有这个文件会创建一个)
  26. // data 要写入文件的内容
  27. // option 文件编码
  28. // callback 写入后执行的回调
  29. let code = 'function sum (a, b) {return a + b}';
  30. fs.writeFile('./a.js', code, 'utf8', (err, data) => {
  31. // err 写入失败时是一个对象,写入成功是 null
  32. if (err) {
  33. console.log('写入失败');
  34. // 一般写入文件失败是由于文件夹权限有问题
  35. } else {
  36. // console.log('写入成功');
  37. }
  38. });
  39. // fs.writeFile() 是覆盖式写入,原文件中的内容会被覆盖掉;如果要追加的话,先把原来的文件内容读取出
  40. // 来,然后再拼接上咱们要写入的内容,然后再一并写回去;
  41. // 同步写入:
  42. // fs.writeFileSync(path, data, option)
  43. // path 文件名(含路径)
  44. // data 写入文件的内容
  45. // option 编码
  46. // 同步写入没有返回值
  47. let htmlStr = `<!DOCTYPE>
  48. <html>
  49. <head>
  50. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  51. <meta name="description" content="发上等愿,结中等缘,享下等福">
  52. <meta name="keywords" content="前端好,前端好个锤子">
  53. <title>这是一个title标签</title>
  54. <!--TDK SEO时要设置-->
  55. </head>
  56. <body>
  57. <div>
  58. 这是一个划时代的app
  59. </div>
  60. </body>
  61. <script>
  62. alert('真香')
  63. </script>
  64. </html>`;
  65. let wdata = fs.writeFileSync('../a.html', htmlStr, 'utf8');
  66. console.log(wdata);
  67. // 向文件中追加内容:
  68. // 异步追加
  69. // fs.appendFile(path, data, option, callback)
  70. // path 文件名(含路径)
  71. // data 写入文件的内容
  72. // option 编码
  73. // callback 追加后的回调
  74. let code2 = '\n\rfunction minus(a, b) {return a - b}';
  75. // \n 换行
  76. // \n\r 空行
  77. /*fs.appendFile('./b.js', code2, 'utf8', (err, data) => {
  78. if (err) {
  79. console.log(err);
  80. } else {
  81. console.log('追加成功');
  82. }
  83. });*/
  84. // 同步追加
  85. // fs.appendFileSync(path, data, option)
  86. // 参数和异步相同
  87. fs.appendFileSync('./b.js', code2, 'utf8');

二、http 模块

前端发起请求,获取数据,然后拿到数据渲染到页面中;后端(服务端),响应请求,发送数据
前后端通过 http 协议通信,前端通过 http 发请求,向服务器要数据;服务端处理 http 请求,通过 http 协议向客户端发送数据;
http 模块:http 是 Node.js 的内置模块;是用来处理客户端的 http 请求的

  1. let http = require('http');
  2. let fs = require('fs');
  3. // 1. 处理客户端 http 请求,首先要创建一个服务;
  4. // http.createServer() 创建一个服务
  5. let server = http.createServer(function (request, response) {
  6. // 具体的处理 http 请求的代码要写在这个回调函数中;只要客户端发送一个 http 请求,这个回调函数就会执行一次;
  7. // request 请求对象 这个对象中包含了客户端的请求中所有的信息;
  8. // response 响应对象 这个对象中包含了所有用来响应客户端所需要的方法和属性;
  9. console.log('请求来了');
  10. // 把 index.html 响应给客户端
  11. // 首先我们需要把 index.html 读出来,然后把读取的结果作为响应内容发送给客户端;
  12. fs.readFile(__dirname + '/index.html', (err, data) => {
  13. if (err) {
  14. response.end('读取失败')
  15. } else {
  16. response.end(data); // 向客户端发送响应数据
  17. }
  18. });
  19. // 我们在响应客户端请求的时候,现在并没有判断客户端请求的是什么;当客户端收到 index.html 以后会解析 html,解析的时候遇到 script 标签,而 script 会再向服务器发送请求,而此时我们的服务只会响应 index.html 的内容,所以 script 收到的就是 index.html 的内容;
  20. });
  21. // 2. 服务还需要监听端口号(练习阶段不要使用3000以下)
  22. // 端口的范围:0-65535
  23. // server.listen (端口号, 监听端口成功执行的回调)
  24. server.listen(8000, () => console.log('port 8000 is on'));
  25. // 一个端口只能供一个服务监听,当前8000端口被 server 占用了,其他的服务就不能再用8000端口了;

写完脚本以后,还需要到命令行里启动这个服务:node 加文件名,然后去浏览器中访问:localhost:8000
为什么用 localhost?
因为正常的请求是访问 url ,然后 DNS 负责把 url 解析成 ip 地址,然后请求 ip 地址,但是服务器是运行在本地,本地的 ip 127.0.0.1,而 127.0.0.1 就是 localhost。
此时我们的电脑上既运行着客户端又运行着服务端;浏览器是客户端,用 node 启动的 js 脚本是服务端。修改了服务端的程序需要重启 server

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
  7. </head>
  8. <body>
  9. <h1>这是index.html</h1>
  10. <div>
  11. <a href="/a.html">这是A页面</a>
  12. </div>
  13. <div><a href="/b.html">这是B页面</a></div>
  14. </body>
  15. </html>

三、url 模块

  1. // url 模块也是 Node.js 的内置模块,是用来解析 url 的;
  2. let http = require('http');
  3. let url = require('url');
  4. let fs = require('fs');
  5. // 1. 创建一个服务
  6. let server = http.createServer((req, res) => {
  7. // console.log(req.url); 客户端请求的 url
  8. // console.log(req.headers.cookie); 客户端带来的 cookie
  9. let urlObj = url.parse(req.url, true); // url.parse() 解析请求 url 的方法,第二个参数传 true,把 url 问号传参格式化成一个对象,并在挂载在 query 属性上
  10. console.log(urlObj);
  11. // pathname 客户端请求的路径
  12. // search 客户端问号传参的内容(带问号)
  13. // query 客户端传递的查询字符串
  14. });
  15. // 2. 监听端口号
  16. server.listen(8000, () => console.log('port 8000 is on'));

四、根据不同路径返回不同内容

  1. // 根据请求的路径的不同返回不同的 html
  2. // 获取当前的请求路径,读取路径对应的 html 然后返回给客户端即可;
  3. let http = require('http');
  4. let url = require('url');
  5. let fs = require('fs');
  6. // 1. 创建一个服务
  7. let server = http.createServer((req, res) => {
  8. // 1.1 解析 url
  9. let urlObj = url.parse(req.url, true);
  10. let { pathname } = urlObj;
  11. // server 启动时所在的路径就是根目录 /
  12. // /a.html -> 读取 /a.html 文件
  13. // /b.html -> 读取 /b.html 文件
  14. // console.log('pathname is ' + pathname);
  15. // console.log(__dirname + pathname);
  16. // 当我们访问 localhost:8000 时 pathname 是 / ,此时并没有 / 的html
  17. // 加一个判断,判断 pathname 是不是/,如果是 / 就要读 index.html
  18. let filePath = '';
  19. if (pathname === '/') {
  20. filePath = __dirname + '/index.html'
  21. } else {
  22. filePath = __dirname + pathname;
  23. }
  24. fs.readFile(filePath, function (err, data) {
  25. if (err) {
  26. res.end('NOT FOUND')
  27. } else {
  28. res.end(data);
  29. }
  30. })
  31. });
  32. // 2. 监听一个端口号
  33. server.listen(8000, () => console.log('port 8000 is on'));
  34. // 服务端响应如 html、css、js、图片等文件服务称为静态资源服务,html、css、js 等文件称为静态资源;
  35. // 如果 pathname 类似 /home/help/search ,这种请求路径不是具体的文件,一般都是 ajax 接口;一般都是处理动态的请求,根据客户端传递的数据返回不同的内容;

a.html

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>Document</title>
  9. <link rel="stylesheet" href="/a.css">
  10. </head>
  11. <body>
  12. <h1>
  13. A
  14. </h1>
  15. <a href="/">返回首页</a>
  16. <img src="/3.png" alt="">
  17. <script src="/a.js"></script>
  18. </body>
  19. </html>

b.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h1>
  9. B
  10. </h1>
  11. <a href="/">返回首页</a>
  12. </body>
  13. </html>

五、响应与 content-type

  1. // Content-Type:
  2. // 服务端在响应客户端的请求的时候要设置响应内容的内容类型,即 Content-type;当客户端收到服务端的响应内容后,会按照这个 Content-type 解析响应的内容;
  3. // Content-type 是一个响应头;
  4. let http = require('http');
  5. let url = require('url');
  6. let fs = require('fs');
  7. let contentTypes = {
  8. html: 'text/html',
  9. css: 'text/css',
  10. js: 'text/javascript',
  11. png: 'image/png',
  12. ico: 'image/x-icon'
  13. };
  14. // 1. 创建一个服务
  15. let server = http.createServer((req, res) => {
  16. // 1.1 解析url
  17. let urlObj = url.parse(req.url, true);
  18. let { pathname } = urlObj;
  19. // 根据 pathname 里面的拓展名,判断到底内容类型是什么;.html -> text/html; .css -> text/css
  20. // /a.html
  21. // /a.css
  22. // /a.js
  23. // /3.png
  24. // /
  25. let extReg = /\.(\w+)/;
  26. let types = extReg.exec(pathname); // 正则捕获,如果捕获到返回数组,捕获不到返回 null
  27. if (types) {
  28. let ext = types[1];
  29. console.log(ext);
  30. res.setHeader('Content-Type', contentTypes[ext]);
  31. // res.setHeader(key, value); 设置响应头信息,key 和 value 都是字符串类型的;
  32. }
  33. let filePath = '';
  34. if (pathname === '/') {
  35. res.setHeader('Content-Type', contentTypes.html);
  36. filePath = __dirname + '/index.html'
  37. } else {
  38. filePath = __dirname + pathname;
  39. }
  40. fs.readFile(filePath, function (err, data) {
  41. if (err) {
  42. res.end('NOT FOUND')
  43. } else {
  44. res.end(data);
  45. }
  46. })
  47. });
  48. // 2. 监听一个端口号
  49. server.listen(8000, () => console.log('port 8000 is on'));

六、MIME 依赖包

  1. // MIME : 多用途互联网邮件拓展;每种文件都有自己特有的 MIME 类型,这个类型就是在响应的时候需要设置的内容类型;
  2. // mime 依赖包,是一个第三方的模块,其中包含了绝大多数的文件的 MIME 类型;
  3. // 使用第三方的依赖包:
  4. // 1. 安装 mime :yarn add mime --save
  5. // 2. 引入第三方的模块
  6. let mime = require('mime');
  7. let http = require('http');
  8. let url = require('url');
  9. let fs = require('fs');
  10. let server = http.createServer((req, res) => {
  11. // 1.1 解析 url
  12. let urlObj = url.parse(req.url, true);
  13. let { pathname } = urlObj;
  14. // 使用 mime 设置内容类型:mime.getType(pathname)
  15. // getType 方法会返回 pathname 对应的内容类型
  16. let filePath = '';
  17. if (pathname === '/') {
  18. filePath = __dirname + '/index.html';
  19. res.setHeader('Content-Type', 'text/html'); // mime.getType() 不能处理 / ;所以需要单独设置
  20. } else {
  21. filePath = __dirname + pathname;
  22. res.setHeader('Content-Type', mime.getType(pathname));
  23. }
  24. fs.readFile(filePath, function (err, data) {
  25. if (err) {
  26. res.end('NOT FOUND')
  27. } else {
  28. res.setHeader('set-cookie', 'name=mabin;path=/;'); // 在服务端操作 cookie;就是设置 set-cookie 的响应头
  29. res.end(data);
  30. }
  31. })
  32. });
  33. // 2. 监听一个端口号
  34. server.listen(8000, () => console.log('port 8000 is on'));

Nodejs报错定位行号.png