Node.js —初识Node.js、fs 文件系统模块、path 路径模块、http 模块

本文介绍了Node.js的基础知识,包括DOS命令操作、Node.js的简介和用途、学习路径。深入讲解了fs文件系统模块,如fs.readFile()和fs.writeFile()的使用,以及解决路径动态拼接问题的方法。此外,还详细阐述了path模块的path.join()和path.basename()等功能。最后,探讨了http模块,如何创建web服务器,并根据不同url响应http内容。通过学习,你可以了解Node.js操作文件和构建web服务器的基本技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标:

  • 能够知道什么是Nodejs
  • 能够知道Node.js 可以做什么
  • 能够说出 Nodejs 中的JavaScript的组成部分
  • 能够使用fs模块读写操作文件
  • 能够使用path模块处理路径
  • 能够使用http模块写一个基本的web服务器 
     

1. DOS基础操作

1.1 常用的命令

1、怎么打开DOS命令窗口(小黑屏)、CMD 窗口、终端、shell
      ---打开菜单—-运行---->cmd--->回车 ;或者 win+r,输入cmd,回车。

2、什么是DOS命令?
        可以完全完成文件的新建、编辑、保存、删除等一系列操作。

3、mkdir abc(非必须掌握)
        创建一个目录,起名abc                                                                                                                     cd 目录名——进入到指定目录;                                                                                                        md 目录名——创建一个文件夹;                                                                                                      rd 目录名——删除一个文件夹         

        直接上箭头可以快速定位到上一次执行的命令

        tab 键,能够快捷补全路径

        esc 键,能够快速清空当前已输入的命令

        cls  清屏

4、切换盘符
        直接输入盘符就行:
        c:回车
        d:回车

5、切换目录(非常重要,必修掌握)
        使用cd命令来完成命令的切换。(change directory)
        语法格式是:cd 路径
        路径包括相对路径和绝对路径。
            在window系统中路径起点是盘符的都是绝对路径: c:\User\Administrator
            相对路径是相对于当前而言,从当前所在的位置作为起点,一定不会以盘符为起点
            
        注意:
            cd .. 回到上级路径
            cd \ 直接回到根路径
            cd . 代表当前路径。(cd命令用不着。以后配置环境变量的时候一个点有用处)


 6、dir 查看当前目录的所有文件
    
 7、exit 退出DOS命令窗口
    
 8、del命令,删除一个或多个文件夹
        删除T1.class文件:del T1.class
        删除所有以class结尾的文件,支持模糊匹配:del *class
        
 9、怎么查看本机的ip地址?
        ipconfig(ip地址的配置信息)
        ipconfig /all 查看更详细的网络信息
        
 10、怎么查看两台计算机是否可以正常通信?
        ping命令
            语法格式:
                ping ip地址
                ping 域名
                
        ping www.baidu.com
        ping 61.135.169.121  (是百度的ip地址)
        ping 61.135.169.121 -t  (-t参数表示一直ping,可以查看网络是否稳定)
        ctrl+c 组合键 强行终止一个正在执行的命令


11、文本编辑快捷键(非常重要,必修掌握,少用鼠标,多用组合键)
    常用的组合键:
        复制 ctrl+c
        粘贴 ctrl+v
        剪切 ctrl+x
        保存 ctrl+s
        
        撤销 ctrl+z
        重做 ctrl+y
        全选 ctrl+a
        查找 ctrl+f
        截图 Alt+A
        
 12、光标在行首或行尾,想要选中一行
        shift+fn+home/end
        回到文件头或文件尾
        ctrl+fn+home/end
        
        选中一个单词:鼠标双击(或ctrl+shift+左/右箭头)
        选中一行:鼠标三击

13、环境变量(windowe采统中的变量)

此电脑—右键属性—高级系统设备—高级—环境变量

path环境变量中保存的是一个一个的路径,路径之间使用;隔开

作用:当我们在命令行窗口中调用一个命令,或访问一个文件时,系统会先在当前文件夹中寻找,如果找不到则依次去path的路径下寻找,如果找到则直接使用,如果没有找到则继续向下一个路径去寻找,如果所有的路径中都没有找到,则报错。
可以将一些常用的文件或程序的路径添加到path下,这样我们就可以在任意位置来访问这些文件了

1. 初识 Node.js

1.1 Node.js 简介

  1. 浏览器是 JavaScript 的前端运行环境。
  2. Node.js 是 JavaScript 的后端运行环境。
  3. Node.js 无法调用 DOM 和 BOM 等浏览器内置API.

1.2 Node.js 可以做什么

Node.js 作为一个JavaScript的运行环境,仅仅提供了基础的功能和API。然而,基于Node.js 提供的这些基础功能,很多强大的工具和框架如雨后春笋,层出不穷,所以学会了 Nodejs,可以让前端程序员胜任更多的工作和岗位:
① 基于Express 框架(http://www.expressjs.com.cn/),可以快速构建 Web 应用
② 基于 Electron 框架(https://electronjs.org/),可以构建跨平台的桌面应用
③ 基于restify 框架(http://restify.com/),可以快速构建API 接口项目
④ 读写和操作数据库、创建实用的命令行工具辅助前端开发、etc..

总之:Node.js 是大前端时代的“大宝剑”,有了 Node.js 这个超级buff的加持,前端程序员的行业竞争力会越来越强!

1.3  Node.js 学习路径

JavaScript 基础语法 + Node.js 内置 API 模块(fs、path、http等)+ 第三方 API 模块(express、mysql 等)

1.4 在Node.js 环境中执行 JavaScript 代码

  1. 打开终端(可以直接在目标文件地址栏输入cmd回车 。或者在目标文件 shift + 鼠标右键 选择打开powershell窗口)

  2. 输入 node 要执行的 js 文件的路径

2. fs 文件系统模块

2.1 什么是 fs 文件系统模块

fs模块是 Nodejs官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。例如:
fs.readFile() 方法,用来读取指定文件中的内容
fs.writeFile() 方法,用来向指定的文件中写入内容

如果要在 JavaScript 代码中,使用 fs 模块来操作文件,则需要使用如下的方式先导入它:

const fs = require('fs')

2.2 读取指定文件中的内容

2.2.1  fs.readFile() 的语法格式

使用 fs.readFile() 方法,可以读取指定文件中的内容,语法格式如下:

fs.readFile(path[, options],callback)

参数1:必选参数,字符串,表示文件的路径。
参数2:可选参数,表示以什么编码格式来读取文件。
参数3:必选参数,文件读取完成后,通过回调函数像到读取的结果。

// 1. 导入 fs 模块,来操作文件
const fs = require('fs');
// 2. 调用 fs.readfile() 方法读取文件
// 参数1:读取文件的存放路径
// 参数2:读取文件时采用的编码格式,默认utf8
// 参数3:回调函数,拿到读取失败和成功的结果 err  dataStr
fs.readFile('./01.txt', 'utf8', function (err, dataStr) {
    // 打印失败的结果,
    // 如果读取成功,则err的值为 null
    // 如果读取失败,则err的值为错误对象,dataStr的值为undefined
    // console.log(err);
    // console.log('---------------');
    // 打印成功的结果
    // console.log(dataStr);
    if (err) {
        console.log('文件读取失败' + err.message);
    } else {
        console.log('文件读取成功,内容是:' + dataStr);
    }
})

 

2.2.1  fs.writeFile() 的语法格式

使用fs.writeFile() 方法,可以向指定的文件中写入内容,语法格式如下:

 fs.writeFile(file, data[, options], callback)

参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径。
参数2:必选参数,表示要写入的内容
参数3:可选参数,表示以什么格式写入文件内容,默认值是utf8
参数4:必选参数,文件写入完成后的回调函数

const fs = require('fs');
fs.writeFile('./02.txt', 'abcd', function (err) {
    // 如果文件写入成功,则err的值等于null
    // 如果文件写入失败,则err的值是一个错误对象
    // console.log(err);//null
    if (err) {
        return console.log('文件写入失败!' + err.message);
    } else {
        console.log('文件写入成功!');
    }
})

//写了 return 可以写 else 也可以不写,没写return一定要else

新写入的内容会覆盖旧的内容! 

考试成绩整理案例:

// 一、导入fs模块
const fs = require('fs')
// 二、调用fs.readFile() 读取文件内容
fs.readFile('./03.成绩.txt', 'utf8', function (err, data) {
    if (err) {
        return console.log('读取失败!');
    }
    // console.log('读取成功!' + data);//读取成功!小红=90   小白=100   小蓝=60   小黑=99   小绿=77
    // 1. 先把成绩的数据按照空格进行分割,存到一个数组里面
    const arrOld = data.split('   ') //用const声明后面不能对arrOld进行修改
    // console.log(arrOld);//[ '小红=90', '小白=100', '小蓝=60', '小黑=99', '小绿=77' ]
    // 2. 循环分割后的数组,对每一项数据,进行字符串的替换操作
    const arrNew = []
    arrOld.forEach(items => {
        arrNew.push(items.replace('=', ':'))
    });
    // console.log(arrNew);//[ '小红:90', '小白:100', '小蓝:60', '小黑:99', '小绿:77' ]
    // 3. 把新数组中的每一项,进行合并,得到一个新的字符串
    const newStr = arrNew.join('\n') //  写 \r\n 也可以
    // console.log(newStr);
    // 三、调用fs.writeFile() 把处理完毕的成绩,写入到新文件中(不能写在外面,写在外面用不了newStr)
    fs.writeFile('./03.整理后的成绩.txt', newStr, function () {
        if (err) {
            return console.log('写入文件失败!');
        }
        console.log('写入文件成功!');
    })
})

2.3 fs 模块 - 路径动态拼接的问题

在使用fs模块操作文件时,如果提供的操作路径是以 ./ ../ 开头的相对路径时,很容易出现路径动态拼接错误的问题。
原因:代码在运行的时候,会以执行node命令时所处的目录,动态拼接出被操作文件的完整路径。
解决方案:在使用 fs 模块操作文件时,直接提供完整的路径,不要提供 ./ 或 ../ 开头的相对路径,从而防止路径动态拼接的问题。

const fs = require('fs');
// 直接提供完整的路径,  移植性非常差,不利于维护
// fs.readFile('D:\\gongyong\\web\\autostudy\\7. Node.js\\1-code\\01.txt', 'utf8', function (err, dataStr) {
//     if (err) {
//         console.log('文件读取失败' + err.message);
//     } else {
//         console.log('文件读取成功,内容是:' + dataStr);
//     }
// })
// __dirname 表示当前文件所处目录(以后都这样写)
fs.readFile(__dirname + '/01.txt', 'utf8', function (err, dataStr) {
    if (err) {
        console.log('文件读取失败' + err.message);
    } else {
        console.log('文件读取成功,内容是:' + dataStr);
    }
})
//后面会学到如何代替 + 拼接路径

 

3. path 路径模块

3.1 什么是 path 路径模块 

path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求。例如:
path.join() 方法,用来将多个路径片段拼接成一个完整的路径字符串
path.basename() 方法,用来从路径字符串中,将文件名解析出来

如果要在JavaScript代码中,使用path模块来处理路径,则需要使用如下的方式先导入它:

const path = require('path')

3.2 路径拼接

3.2.1  path.join() 的语法格式

使用 path.jion() 方法,可以将多个路径片段拼接成一个完整的路径字符串

path.join([...paths])
  • ...paths <string> 路径片段的序列; 
  • 返回值:<string>
const path = require('path')
const fs = require('fs')

//  ../ 会覆盖掉(抵消)前面一个路径,(有几个 ../ 就抵消几个路径)
// const pathStr = path.join('/a', '/b/c', '../', 'd', 'e')
// console.log(pathStr);// \a\b\d\e

fs.readFile(path.join(__dirname, '/01.txt'), 'utf8', function (err, data) {
    if (err) {
        return console.log('读取失败!');
    }
    console.log('读取成功!' + data);
})

注意:今后凡是遇到路径拼接的问题,都要使用  path.join() 方法进行处理。不要直接使用 + 进行字符串的拼接

 

3.3 获取路径中的文件名

3.3.1 path.basename() 的语法格式

path.basename(paths[,ext])
  •  path <string> 必选参数,表示一个路径的字符串
  • ext <string> 可选参数,表示文件扩展名
  • 返回:<string> 表示路径中的最后一部分

 

3.4  获取路径中的文件扩展名

3.4.1 path.extname() 的语法格式

 path.extname(path)
  •   path <string> 必选参数,表示一个路径的字符串
  • 返回:<string> 返回得到的扩展名字符串
// 导入path模块
const path = require('path')

// 文件的存放路径
const fpath = 'a/b/c/index.html'
const fext = path.extname(fpath)
console.log(fext); //.html

 百度换肤案例仿时钟案例:

// 1.1 导入fs文件系统模块
const fs = require('fs');
// 1.2 导入 path模块
const path = require('path');

// 1.3 定义正则表达式,分别匹配 <style></style> 和 <script></script> 标签
const regStyle = /<style>[\s\S]*<\/style>/;    //为免斜杆冲突,要加一个反斜杠
const regScript = /<script>[\s\S]*<\/script>/;

// 2.1 调用fs.readFile()读取文件
fs.readFile(path.join(__dirname, '/模仿时钟案例素材/02-百度换肤.html'), 'utf8', function (err, dataStr) {
    // 如果读取失败
    if (err) {
        return console.log('读取文件失败!' + err.message);
    }

    // console.log('读取文件成功!' + dataStr);
    // 2.2 读取文件成功后,调用对应的三个方法,分别拆解出css、js、html文件
    resolveCss(dataStr);
    resolveJs(dataStr);
    resolveHtml(dataStr);
})

// 3.1 处理css脚本
function resolveCss(htmlStr) {
    // 3.2 利用正则方法exec提取需要的内容
    const r1 = regStyle.exec(htmlStr);
    // console.log(r1);
    // 3.3 将提取出来的样式字符串,进行替换操作
    const newCss = r1[0].replace('<style>', '').replace('</style>', '');
    // console.log(newCss);
    // 3.4 调用fs.writeFile()将提取的样式写入 clock 文件中 index.css文件
    fs.writeFile(path.join(__dirname, '/clock/index.css'), newCss, function (err) {
        if (err) {
            console.log('写入css脚本失败!');
        }
        console.log('写入css脚本成功!');
    })
}

// 4.1 处理js脚本
function resolveJs(htmlStr) {
    // 4.2 利用正则方法exec提取需要的内容
    const r2 = regScript.exec(htmlStr);
    // console.log(r2);
    // 4.3 将提取出来的样式字符串,进行替换操作
    const newJs = r2[0].replace('<script>', '').replace('</script>', '');
    // console.log(newJs);
    // 4.4 调用fs.writeFile()将提取的样式写入 clock 文件中 index.js文件
    fs.writeFile(path.join(__dirname, '/clock/index.js'), newJs, function (err) {
        if (err) {
            console.log('写入js脚本失败!');
        }
        console.log('写入js脚本成功!');
    })
}

// 5.1 处理html脚本
function resolveHtml(htmlStr) {
    // 5.2 使用字符串的 replace,把内嵌的style和script替换成外联的链接
    const newHtml = htmlStr
        .replace(regStyle, '<link rel="stylesheet" href="./index.css">')
        .replace(regScript, '<script src="./index.js"></script>');
    // console.log(newHtml);
    // 5.3 调用fs.writeFile()将得到的html写入 clock 文件中 index.html文件
    fs.writeFile(path.join(__dirname, '/clock/index.html'), newHtml, function (err) {
        if (err) {
            console.log('写入html页面失败!');
        }
        console.log('写入html页面成功!');
    })
}

4. http 模块

4.1 什么是http模块

回顾:什么是客户端,什么是服务器?
在网络节点中,负责消费资源的电脑,叫做客户端;负责对外提供网络资源的电脑,叫做服务器。

http模块是 Node.js 官方提供的、用来创建 web服务器的模块。通过http模块提供的 http.createServer()方法,就能方便的把一台普通的电脑,变成一台Web服务器,从而对外提供 Web 资源服务。

如果要希望使用http模块创建Web服务器,则需要先导入它:

const http = require("http")

服务器和普通电脑的区别在于,服务器上安装了web服务器软件,例:IIS、Apache 等。通过安装这些服务器软件一台普通的电脑变成一台web服务器。

在Nodes中,我们不需要使用IS、Apache等这些第一方web服务器软件。因为我们可以基于Node.js 提供的 http 模块, 通过几行简单的代码 就能轻松的手写一个服务器软件,从而对外提供web服务。

4.2 服务器相关的概念 

4.2.1 IP地址

IP地址就是互联网上每台计算机的唯一地址,因此IP地址具有唯一性。如果把”个人电脑”比作”一台电话”,那么 “1P地址” 就相当于 “电话号码”,只有在知道对方 IP 地址的前提下,才能与对应的电脑之间进行数据通信。
IP 地址的格式:通常用“点分十进制”表示成 (a.b.c.d) 的形式,其中,abcd 都是0~255之间的十进制整数。例如:用点分十进表示的IP地址(192.168.1.1)

注意:
① 互联网中每台Web 服务器,都有自己的IP 地址,例如:大家可以在Windows的终端中运行ping www.baidu.com 命令,即可查看到百度服务器的IP 地址。
在开发期间,自己的电脑既是一台服务器,也是一个客户端,为了方便测试,可以在自己的浏览器中输入127.0.0.1 或者 localhost 这个 IP地址,就能把自己的电脑当做一台服务器进行访问了。

域名服务器就是提供IP地址域名之间转换服务的服务器。

4.2.2 端口号

  • 每个端口号不能同时被多个web服务占用
  • 在实际应用中,URL 中的 80 端口可以被省略

4.3 创建最基本的 web 服务器

4.3.1.  创建 web 服务器的基本步骤

  • 步骤1: 导入http模块
    const http = require("http")
  •  步骤2: 创建web服务器实例
    //调用 createServer() 方法创建web服务器实例
    const server = http.createServer()
  •  步骤3:为服务器实例绑定request 事件,监听客户端的请求 
    // 使用服务器实例的 .on() 方法,为服务器绑定一个 request 事件
    server.on('request' , (req, res) => {
        //只要有客户端请求我们自己的服务器,就会触发 request 事件,从而调用这个事件处理函数
        console.log('Someone visit our web server');
    })
  • 步骤4:启动服务器
//调用 server.listen(端口号,cb回调) 方法,即可启动web服务器
server.listen(80, () => {
    console.log('http server running at http://127.0.0.1');
})

实例: VS 顶部点终端,选新建终端,下面像 在控制台一样输入,注意:端口号不能重复            ctrl + c 停止服务器          如果更改了代码内容,要结束终端再重新打开。

// 1. 导入http模块
const http = require('http');
// 2. 创建web服务器实例
const server = http.createServer();
// 3. 为服务器实例绑定 request 事件,监听客户端的请求 
server.on('request', function (req, res) {
    console.log('Someone visit our web server');
})
// 4. 启动服务器
server.listen(80, function () {
    console.log('http server running at http://127.0.0.1:80');//如果是80就可以省略
})

4.3.2 req 请求对象

// 导入 http 模块
const http = require('http');
// 创建服务器
const server = http.createServer()
// 绑定request事件
// req是请求对象,包含了与客户端相关的数据和属性
server.on('request', (req) => {
    // req.url 是客户请求的 URL 地址
    const url = req.url;
    // req.method 是客户端请求的method类型
    const method = req.method;
    const str = `Your request url is ${url},and request method is ${method}`;
    console.log(str);
})
// 启动服务器
server.listen(80, () => {
    console.log('server running at http://127.0.0.1');
})

4.3.3 res 响应对象 

// 导入 http 模块
const http = require('http');
// 创建服务器
const server = http.createServer()
// 绑定request事件
// req是请求对象,包含了与客户端相关的数据和属性
server.on('request', (req, res) => {
    // req.url 是客户请求的 URL 地址
    const url = req.url;
    // req.method 是客户端请求的method类型
    const method = req.method;
    const str = `Your request url is ${url},and request method is ${method}`;
    console.log(str);
    // 调用 res.end() 方法,向客户端响应一些内容
    res.end(str);  //在下面的终端复制地址在浏览器打开就可以看到内容(用的是get请求)
     // (如果想要发一个post请求,去postman测试工具选择post方式)
})
// 启动服务器
server.listen(80, () => {
    console.log('server running at http://127.0.0.1');
})

4.3.4 解决中文乱码问题

const http = require('http');
const server = http.createServer();
server.on('request', function (req, res) {
    // 定义一个字符串。包含中文内容
    const str = `请求的url地址是${req.url},请求的method类型是${req.method}`;
    // res.end() 将内容相应给客户端
    // 调用res.setHeader() 方法,设置 content-Type 响应头,解决中文乱码问题
    res.setHeader('content-Type', 'text/html;charset=utf-8');//固定写法
    res.end(str);
})
server.listen(80, function () {
    console.log('server running at http://127.0.0.1');
})

4.4 根据不同的 url 响应不同的 http 内容

4.4.1 核心实现步骤 

 1. 获取请求的 url 地址
 2. 设置默认的响应内容为 404 Not found
 3. 判断用户请求的是否为 //index.html 首页
 4. 判断用户请求的是否为 /about.html 关于页面
 5. 设置 Content-Type 响应头,防止中文乱码
 6. 使用 res.end() 把内容响应给客户端

实例: 

const http = require('http');
const server = http.createServer();
server.on('request', function (req, res) {
    // 获取请求的 url 地址
    const url = req.url;
    // 设置默认的响应内容为 404 Not found
    let content = '<h1>404 Not found</h1>';
    // 判断用户请求的是否为 / 或 /index.html 首页
    // 判断用户请求的是否为 /about.html 关于页面
    if (url === '/' || url === '/index.html') {
        content = '<h1>首页</h1>';
    } else if (url === '/about.html') {
        content = '<h1>关于页面</h1>';
    }
    // 设置 Content-Type 响应头,防止中文乱码
    res.setHeader('Content-Type', 'text/html;charset=utf-8');
    // 使用 res.end() 把内容响应给客户端
    res.end(content);
})
server.listen(80, function () {
    console.log('server running at http://127.0.0.1');
})

4.4.2 案例 - 实现百度换肤的web服务器 :

1. 核心思路

  • 把文件的实际存放路径,作为每个资源的请求 url 地址

2. 实现步骤

  1. 导入需要的模块
  2. 创建基本的web服务器
  3. 将资源的 请求 url 地址映射为 文件的存放路径
  4. 读取文件内容并响应给客户端
  5. 优化资源的请求路径
// 1. 导入需要的模块
// 1.1 导入http模块,用于创建服务器
const http = require('http');
// 1.2 导入fs模块,用于读取文件
const fs = require('fs');
// 1.3 导入path模块,用于处理路径问题
const path = require('path');

// 2.1 创建基本的web服务器
const server = http.createServer();
// 2.2 监听web服务器的request事件
server.on('request', function (req, res) {
    // 3.1 获取到客户端请求的url地址
    //  /clock/index.html
    //  /clock/index.css
    //  /clock/index.js
    const url = req.url;
    // 3.2 将资源的 请求 url 地址映射为 文件的存放路径
    // const fpath = path.join(__dirname, url);
    // 5.1 预定义一个空白的文件存放路径
    let fpath = '';
    if (fpath === '/') {
        fpath = path.join(__dirname, './clock/index.html');
    } else {
        //  /index.html
        //  /index.css
        //  /index.js
        fpath = path.join(__dirname, '/clock', url);
    }
    // 4.1 根据映射过来的路径读取文件内容并响应给客户端
    fs.readFile(fpath, 'utf8', (err, dataStr) => {
        // 4.2 读取失败,向客户端响应固定的“错误消息”
        if (err) {
            return res.end('404 Not found');
        }
        // 4.3 读取成功,将读取成功的内容响应给客户端
        // res.setHeader('Content-Type', 'text/html;charset=utf-8')
        res.end(dataStr)
    })
})
// 2.3 启动服务器
server.listen(80, function () {
    console.log('server running at http://127.0.0.1');
})

注意: 由于使用的案例由图片构成,所以显示不出来,但审查元素是成功的。虽然但是,我也不知道为啥图片不能显示,但代码应该是没有错的...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值