nodejs01——安装及使用、服务端及客户端、commonjs规范、fs模块的使用(文件操作及目录操作)、stream、buffer、WebServer、端口、动态资源及静态资源、头信息、请求方式
nodejs的安装及使用
服务端及客户端
commonjs规范
fs模块的使用(文件操作及目录操作)
stream
buffer
//
Node.js介绍
Node.js 诞生于2009年,Node.js采用C++语言编写而成,是 一个Javascript的运行环境。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境 ,让JavaScript的运行脱离浏览器端,可以使用JavaScript语言 书写服务器端代码。
安装Node.js
Node.js官网下载稳定版本,node偶数版本为稳定版本,奇数版本为非稳定版本。
mac 直接安装 或者 brew来安装
安装完Node.js会自动安装NPM(Node Package Manager):包管理工具;
打开终端cmd,通过指令 node -v 来查看是否安装完成(出现版本号即是安装完成)
查看node版本号;npm -v 来查看npm版本
初步感受nodejs:用nodejs创建一个服务器
index.js
//引入http模块
let http = require("http");
//创建一个服务器
let serve = http.createServer((req,res)=>{console.log("hello");res.write("hello");res.end("hello world");
})
//设置端口号
serve.listen(3000);
index.js可通过node去启动服务,node + index.js路径
通过浏览器访问localhost:3000(服务端)
另一台同局域网下的电脑访问则是客户端
npm i nodemon -g #安装nodemon
nodemon自动刷新node服务,无需Ctrl+C两次刷新
- Google Chrome 默认非安全端口列表,尽量避免以下端口。1, // tcpmux7, // echo9, // discard11, // systat13, // daytime15, // netstat17, // qotd19, // chargen20, // ftp data21, // ftp access22, // ssh23, // telnet25, // smtp37, // time42, // name43, // nicname53, // domain77, // priv-rjs79, // finger87, // ttylink95, // supdup101, // hostriame102, // iso-tsap103, // gppitnp104, // acr-nema109, // pop2110, // pop3111, // sunrpc113, // auth115, // sftp117, // uucp-path119, // nntp123, // NTP135, // loc-srv /epmap139, // netbios143, // imap2179, // BGP389, // ldap465, // smtp+ssl512, // print / exec513, // login514, // shell515, // printer526, // tempo530, // courier531, // chat532, // netnews540, // uucp556, // remotefs563, // nntp+ssl587, // stmp?601, // ??636, // ldap+ssl993, // ldap+ssl995, // pop3+ssl2049, // nfs3659, // apple-sasl / PasswordServer4045, // lockd6000, // X116665, // Alternate IRC [Apple addition]6666, // Alternate IRC [Apple addition]6667, // Standard IRC [Apple addition]6668, // Alternate IRC [Apple addition]6669, // Alternate IRC [Apple addition]
模块化
一、为什么会有模块化
在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即,如今随着前端代码日益膨胀
这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码;
二、Node.js中的模块化 commonjs规范
(Node.js模块化commonjs规范:不存在变量污染,文件独立)
CommonJS就是为JS的表现来制定规范,因为js没有模块的功能所以CommonJS应运而生,它希望js可以在任何地方运行,不只是浏览器中。
1、创建自定义模块
引入一个文件 形式模块
home.js执行文件
console.log("我是 home.js"); //通过require来引入 require("./aModule"); //注意一定要有"./",文件后缀可加可不加。 console.log(a);//undefined,文件间相互独立,为防止变量污染,提高可读性
amodule.js文件
console.log("我是amodule模块111"); let a = 20;
引入文件夹形式模块
- home.js执行文件
require("./aModuledir"); //必须加"./"
aModuleDir里的index.js文件,会自动查找文件夹下的index.js文件执行
console.log("我是aModule模块文件夹");
- 当然也可以配置默认启动文件,在文件夹内新建package.json来指定执行文件
{"name":"aModule","version":"1.0.0","main":"test.js" }
自定义模块的按需导出
通过module.exports 导出; ___dirname , __filename
module.exports = {a:"我是a的值",b(){console.log("我是导出的b函数");} }
引入导出文件
let mymodule = require("bModule"); console.log(mymodule.a); mymodule.b();
或者 通过 exports来导出
exports.fn = function(){console.log("我是fn函数"); }
导入文件
let myfn = require("bModule").fn; myfn(); // 或者 通过解构赋值 let { fn } = require("bModule"); fn();
模块加载的优先级 ,先文件再目录;
///
console.log("我是Ma.js文件");
require("./Mb");
let a = 10;
class Person {constructor() {this.name = "张三";}hobby() {console.log("喜欢篮球");}
}// 按需导出:模块导出
// module.exports = {// a,
// Person
// }// 按需导出:单个导出
exports.a = a;
exports.Person = Person;
// exports 是 module.exports 的引用,也就是module.exports = exports;
// AMD sea.js CMD require.js
console.log("我是index.js");
let Ma = require("./Ma");
// console.log(a);
console.log(Ma.a);// let cai = new Ma.Person();
// cai.hobby();// require("./home");//引入执行home文件夹内的文件// node_modules里的模块: 可不加./ 如下require("mytest")
// let { a, b } = require("mytest");
// console.log(a);
// b();// require("mytest")
// const http = require("http");// npm:包管理器
// dependencies:运行依赖jquery、vue、react ;
// devDependencies:开发依赖 sass less;// 创建node服务器
// const http = require("http");//http是内置模块,可以理解成安装node后就内置有http了
// const serve = http.createServer((req, res) => {// res.write("hello world111");
// res.end();
// });
// serve.listen(3000);
//
2、内置模块;
nodejs内置模块有:Buffer,C/C++Addons,Child Processes,Cluster,Console,Crypto,Debugger,DNS,Domain,Errors,Events,File System,Globals,HTTP,HTTPS,Modules,Net,OS,Path,Process,P unycode,Query Strings,Readline,REPL,Stream,String Decoder,Timers,TLS/SSL,TTY,UDP/Datagram,URL, Utilities,V8,VM,ZLIB;
内置模块不需要安装,外置模块需要安装;
npm包管理器(模块管理器)
NPM(Node Package Manager) 官网的地址是 npm官网
- npm常用指令;
- npm init:引导创建一个package.json文件
- npm help(npm -h) :查看npm帮助信息
- npm version (npm -v) : 查看npm版本;
- npm search:查找
- npm install (npm i):安装 默认在当前目录,如果没有node_modules 会创建文件夹;
- npm install module_name -S 或者–save 即 npm install module_name --save 写入dependencies运行依赖
- npm install module_name -D 或者 —save-dev 即 npm install module_name --save-dev 写入devDependencies开发依赖
- npm install module_name -g 全局安装(命令行使用)
- 指定版本安装模块 npm i module_name @1.0 通过 "@"符号指定;
- npm update(npm -up):更新
- npm remove 或者 npm uninstall:删除
- npm root 查看当前包安装的路径 或者通过 npm root -g 来查看全局安装路径;
fs模块
fs是文件操作模块,所有文件操作都是有同步和异步之分,特点是同步会加上 “Sync” 如:异步读取文件 “readFile”,同步读取文件 “readFileSync”;
文件操作
文件读取:
- 异步读取
let fs = require("fs"); fs.readFile("1.txt",(err,data)=>{if(err){return console.log(err);}console.log(data.toString()); })
第一个参数是读取文件的路径;
第二个参数是读取的编码格式;(可省略不写)utf8
第三个参数是回调函数;- 同步读取文件
let fs = require("fs"); let res = fs.readFileSync("1.txt"); console.log(res.toString());
同步需要拿到返还值;
异步需要回调函数拿到结果;
文件写入:
let fs = require("fs"); //flag配置 "a":追加写入,"w":写入,"r":读取 fs.writeFile("2.txt","我是要写入的内容",{flag:"w"},err=>{if(err){return console.log(err);}console.log("写入成功"); })
文件删除
fs.unlink("2.txt",err=>{if(err){return console.log(err);}console.log("删除成功"); })
复制文件
- 先读取文件再写入文件
function mycopy(src,dest){//src:读取路径;dest:写入路径fs.writeFileSync(dest,fs.readFileSync(src)); } mycopy("1.txt","4.txt");
fs.copyFile("index.html","myindex.html",err=>{if(err){return console.log(err);}console.log("复制成功!");})
- 修改文件名,目录也可以通过rename来操作
fs.rename("1.txt","5.txt",function (err) {if(err){console.log(err);}else{console.log("修改成功");}});
- 判断文件是否存在
fs.exists("4.txt",function (exists) {console.log(exists);})
const fs = require("fs"); //文件操作
// 增删改查;
// 1.文件操作 2.目录操作;// 文件操作
// fs.writeFile("1.txt","我是写入的文字",function(err){// if(err){// return console.log(err);
// }
// console.log("写入成功");
// })// 第三个参数(配置项)a:追加写入;w 写入;r:读取;
// fs.writeFile("1.txt","我是追加的文字",{flag:"a"},function(err){// if(err){// return console.log(err);
// }
// console.log("写入成功");
// })// 文件读取
// fs.readFile("1.txt","utf8",(err,data)=>{// if(err){// return console.log(err);
// }
// console.log(data);
// })
// fs.readFile("1.txt",(err,data)=>{// if(err){// return console.log(err);
// }
// console.log(data.toString());
// })// 所有文件操作 没有加Sync都是异步 否则是同步;
// let data = fs.readFileSync("1.txt");
// console.log(data.toString());// 修改;(修改名称);
// fs.rename("1.txt","2.txt",err=>{// if(err){// return console.log(err);
// }
// console.log("修改成功");
// });// 删除;
// fs.unlink("2.txt",(err)=>{// if(err){// return console.log(err);
// }
// console.log("删除成功");
// })// 复制; 先读取 在写入 的过程;
// fs.copyFile("index.html","myindex.html",err=>{// if(err){// return console.log(err);
// }
// console.log("复制成功!");
// })// 复制
// function mycopy(src,dest){// fs.writeFileSync(dest,fs.readFileSync(src));
// }
// mycopy("index.html","test.html");// 目录操作
// 创建目录
// fs.mkdir("11",err=>{// if(err){// return console.log(err);
// }
// console.log("创建成功");
// })// 修改目录名称
// fs.rename("11", "22", err => {// if (err) {// return console.log(err);
// }
// console.log("修改成功");
// })// 读取目录;
// fs.readdir("22",(err,data)=>{// if(err){// return console.log(err);
// }
// console.log(data);
// })// 删除目录(空文件夹/目录)
// fs.rmdir("11",err=>{// if(err){// return console.log(err);
// }
// console.log("删除成功");
// })// 判断文件或者目录是否存在
// fs.exists("index.html",exists=>{// console.log(exists);
// })// 获取文件或者目录的详细信息;
// fs.stat("index.html",(err,stat)=>{// if(err){// return console.log(err);
// }
// // console.log(stat);
// // 判断文件是否是文件
// // let res = stat.isFile();
// // 是否是一个文件夹;
// let res = stat.isDirectory();
// console.log(res);
// })// 封装删除非空文件夹;
// 先把目录里的文件删除-->删除空目录;
// 22
function removeDir(path) {let data = fs.readdirSync(path);// ["33","1.txt","2.html"];for (let i = 0; i < data.length; i++) {// 是文件或者是目录; --->?文件 直接删除?目录继续查找; let url = path + "/" + data[i];let stat = fs.statSync(url);if (stat.isDirectory()) {//目录 继续查找;removeDir(url);//递归删除} else {// 文件 删除fs.unlinkSync(url);}}// 删除空目录fs.rmdirSync(path);
}
removeDir("22");//执行删除非空文件夹
buffer缓冲区
- buffer的创建
- 直接创建
- 数组创建
- 字符串创建
- 乱码的处理
- buffer转换tostring
// buffer创建
// new Buffer()
// let buffer = Buffer.alloc(10);
// console.log(buffer);
// let buffer = Buffer.from("大家好");
// console.log(buffer);
// let buffer = Buffer.from([0xe5,0xa4,0xa7,0xe5,0xae,0xb6,0xe5,0xa5,0xbd]);
// console.log(buffer.toString());let buffer1 = Buffer.from([0xe5,0xa4,0xa7,0xe5]);
let buffer2 = Buffer.from([0xae,0xb6,0xe5,0xa5,0xbd]);
// // console.log(buffer1.toString());
// let newbuffer = Buffer.concat([buffer1,buffer2]);
// console.log(newbuffer.toString());let { StringDecoder } = require("string_decoder");
let decoder = new StringDecoder();
let res1 = decoder.write(buffer1);
let res2 = decoder.write(buffer2);
console.log(res1+res2);
// console.log(res2);
stream流
- stream流:流与数据处理方面密不可分
- 流的原理
- 流数据的获取
- pipe
- data
- end
- copy的流方法实现
- 加载视图的流方法实现
// stream 流;
const fs = require("fs");
// let res = fs.readFileSync("1.txt");
// console.log(res.toString());
let rs = fs.createReadStream("1.txt");//分量读,一点一点读,防止爆仓内存不足的情况;let ws = fs.createWriteStream("2.txt");
rs.pipe(ws);//把1里面读取的数据写入2内,通过pipe管道写入let num = 0;let str = "";rs.on("data",chunk=>{num++;str += chunk;// console.log(chunk);console.log(num);})// 流完成了;rs.on("end",()=>{console.log(str);})// 流会把数据分成64kb的小文件传输;// 创建一个65kb的文件;
// let buffer = Buffer.alloc(64*1024);
// fs.writeFile("65kb",buffer,err=>{// if(err){// return console.log(err);
// }
// console.log("写入成功");
// })
从浏览器输入 URL 到页面展示过程的过程中发生了什么?
1、在浏览器地址栏输入 URL 并回车/跳转 发送的时候,浏览器会调用内部资源加载器(类似浏览器内置的下载工具或迅雷等)加载相应资源。
依据协议的不同加载方式也不一样:
——1、file协议,根据url路径加载本地资源。
——2、http等协议,根据url加载(下载)网络中的资源。
2、通过IP(如果是域名,则会先通过DNS转成对应IP)定位到指定的目标资源所在的主机,并等待主机处理和响应。
3、主机对每次的请求进行分析,并通过请求携带的端口转发给对应的处理程序(QQ的消息交给QQ这个软件处理,微信的消息交给微信这个软件处理),通常针对 http 这种请求,相关数据交由主机指定的软件进行处理(称为 WebServer APP,如:Nginx、Apache、IIS、Tomcat……)
4、WebServer 分析请求信息,如请求的方式,请求的路径,请求携带的其他各种规定好的或自定的数据。根据这些数据,以及自己定义的业务规则,处理数据,然后进行返回。返回的数据可以是JSON格式的字符串,也可以是HTML格式的字符串,或者各种图片、音频、视频等数据。
5、浏览器接收资源加载器请求(主机返回)的数据,然后根据得到的内容类型进行解析处理。
6、如果浏览器解析过程中,比如解析的是html内容,碰到类似link,script,img等标签,又或者是后续用户的一些行为,如点击a链接,提交一个表单等,再次触发资源加载请求,重复上述步骤……
通常,我们把发送请求(需求)的一方称为:客户端。接收请求(提供服务)的一方成为:服务端。
WebServer
WebServer 本质上就是一个软件,一个用来处理网络数据交互的程序,它可以用任何具备网络编程的语言来实现,如:c、c++、java,python,php 等,我们前面介绍的 Node.js 也可以。
基于 Node.js 构建 WebServer
Node.js 中已经内置提供了一个模块: http
,这个模块就提供了实现 http 所需要的 API:
- 提供了服务端接口,用来响应客户端发送的 http 请求。
- 提供了客户端接口,可以像浏览器一样发送请求到其它服务端。
https://nodejs.org/dist/latest-v12.x/docs/api/http.html
创建 WebServer
我们要创建一个 WebServer,需要使用 http
模块下 http.Server
类来创建一个 Server
对象,我们可以通过一个静态工厂方法 http.createServer
来得到该类的实例对象:
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');// 创建一个 Server 对象
const server = http.createServer();
端口的意义
一台主机的网卡数量是有限的,不可能为主机上的每一个程序去安装一个网卡。为了解决不同的应用程序共享网卡而不至于数据混乱的问题,系统会准备一批端口(类似银行窗口),由需要使用端口进行数据通信的程序去申请(监听),申请成功以后,就可以进行网络数据交互了。
通常,监听端口数据需要程序主动指定。发送请求由系统随机分配,如:
主机:111.111.111.111 监听 8888 端口
客户端发送请求:222:222:222:222:4567 => (发送数据) => 111.111.111.111:8888
注:端口取值范围为:1-65535,即 216 。通常约定1-1023之间的端口为系统常见程序预留端口,1024-5000为通信临时随机端口,5000以后为用户自定端口。
//端口:把数据与具体应用(比如当前server)进行绑定的一个机制
server.listen(8888,"0.0.0.0");//0.0.0.0是通配,默认的;//8888是指定端口进行访问// 方式2
server.listen(8888,()=>{console.log("服务启动成功,访问地址:http://localhost:8888");
});
端口监听
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');// 创建一个 Server 对象
const server = http.createServer();// 监听一个指定的端口,第二参数如果是指定要监听的网卡所在网络的IP(一台机器可能存在多个网卡,一个网卡也可能会在多个不同的网络中,127.0.0.1 默认指本地回环网络,即自己给自己通信的特殊IP,同时有个默认的域localhost,0.0.0.0 表示所有网卡所有IP,可省略),
server.listen(8888, '127.0.0.1', () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});//等同于以下server.on('request', () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});
使用 Node 解析器执行该程序,程序就会进入监听状态(不会退出)
node app.js
处理用户请求
server
会提供一些的事件,我们通过 Node.js 内置的 on
方法来监听这些事件,完成对应的业务处理。
当服务启动成功以后,客户端就可以通过发送对应的 http
请求(http://127.0.0.1:8888)来完成与上述服务器的通信了。
因为浏览器在发送请求的时候,默认端口为 80,所以,如果服务端监听的是 80 端口,那么浏览器在请求过程中可以不需要显式填写端口了,http://127.0.0.1:80 => http://127.0.0.1
request 事件
当服务启动成功以后,我们可以监听 server
对象的 request
事件来处理客户端请求。
// [file: app.js]//...server.on('request', () => {console.log('有客户端发送了一个请求');
});//...
我们还可以在 http.createServer
的时候传入一个 callback
参数,这个 callback
就是 request
事件的回调函数。
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');// 创建一个 Server 对象
const server = http.createServer(() => {console.log('有客户端发送了一个请求');
});server.listen(8888, () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});
在 request
事件回调函数中会自动传入两个参数,供我们进行后续的业务逻辑调用:
- http.IncomingMessage(req):一个 Node.js 封装好的对象,与当前请求的客户端相关信息(客户端请求提交的数据,IP等)和方法都是通过该对象来完成。
- http.ServerResponse(res):也是一个 Node.js 封装好的对象,提供了服务端信息和方法,比如向客户端发送数据的方法就由该对象提供。
http.IncomingMessage 对象(req)
一个 Node.js 封装好的对象,与当前请求的客户端相关信息(客户端请求提交的数据,IP等)和方法都是通过该对象来完成。
一些常用属性和方法:
- url: 当前客户端请求的 url,http://域名:端口 后面的部分,不包含 http://域名:端口。
- headers: 当前客户端请求携带的头信息数据。
- method: 当前客户端所使用的请求方法。
- httpVersion:当前客户端请求所使用的 http 协议的版本。
- on(): 监听一些事件。
http.ServerResponse 对象(res)
也是一个 Node.js 封装好的对象,提供了服务端信息和方法,比如向客户端发送数据的方法就由该对象提供。
一些常用的属性和方法:(write、end、setHeader、statusCode、statusMessage、writeHead)
- write(chunk[, encoding][, callback]):服务端发送数据给客户端的方法,但是需要调用end方法来结束当前请求。
- end([data[, encoding]][, callback]):与write类似。
- setHeader(name, value): 设置发送给客户端的额外信息(头信息)。
- statusCode:响应状态码。
- statusMessage:响应状态码对应的文本。
- writeHead(statusCode[, statusMessage][, headers]):与 end 类似,注意:调用 writeHead 以后不能在进行头信息设置了。
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');// 创建一个 Server 对象
const server = http.createServer((req, res) => {// 代表了客户端的 req 对象console.log('req', req);// 代表了服务端的 res 对象console.log('res', res);
});server.listen(8888, () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});
url 的作用
我们通常会通过一个 URL
来访问不同的内容。这里的 URL
也称为: 统一资源定位符(Uniform Resource Locator)
。
参考:
- https://baike.baidu.com/item/%E7%BB%9F%E4%B8%80%E8%B5%84%E6%BA%90%E5%AE%9A%E4%BD%8D%E7%B3%BB%E7%BB%9F/5937042?fromtitle=url&fromid=110640
- https://en.wikipedia.org/wiki/URL
每一个互联网中的资源(资源可以是一段HTML字符串、HTML文件、CSS文件、JS文件、图片、视频、音频……)都会通过一个 URL
来与之对应,但是这种对应关系需要程序(WebServer)来实现。比如:http://kaikeba.com/js/hello 这个 URL 在找到 kaikeba.com 这个主机(服务器)以后,/js/hello 这个虚拟的 URL 路径会返回对应的内容是什么,它可以直接返回一个字符串,也可以返回一个服务器在某个地方存储的文件,也也也可以是这个服务器去另外一个主机上读取的内容。
req.url
我们可以通过分析每次请求的 url
来获取当前客户端要请求的资源。
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');// 创建一个 Server 对象
const server = http.createServer((req, res) => {// 当前请求的 urlconsole.log('req.url', req.url);
});server.listen(8888, () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});
res.write AND res.end
根据不同的请求 URL 以及当前具体业务逻辑,通过 res
对象的 write
和 end
方法向客户端返回这次请求的结果。
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');
const fs = require('fs');// 创建一个 Server 对象
const server = http.createServer((req, res) => {const url = req.url;let resContent = '';// 针对不同url进行不同的处理if (url == '/') {// 返回一个字符串resContent = 'hello';} else if (url == '/now') {resContent = (new Date).toString();} else if (url == '/kkb.html') {resContent = fs.readFileSync('./kkb.html');} else {resContent = '啥也没有';}res.end(resContent);
});server.listen(8888, () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});
静态资源 Vs 动态资源
许多时候,我们会把资源简单的划分成:
- 静态资源
- 动态资源
静态资源
相对不变的内容(除非你修改了它的内容),类似程序中的 变量与常量。
比如前面 / 、/kkb.html 以及 最后那个 啥也没有,就是静态内容,除非你去修改内容本身,否则访问对应的 URL ,返回的内容永远不变。
动态资源
与静态资源不同,同一个 URL 返回的内容并不固定,比如访问 /now 这个 URL,即使不做任何修改,你就有可能得到不一样的结果,这就是动态资源。
静态资源代理(处理)服务
通常,我们的 WebServer 会提供各种静态资源(html代码、css代码、js代码、图片……),而这些资源我们又通常会通过文件的方式存储在某个地方。为了批量处理这种资源与 URL 的对应关系,我们会根据某种规则(规则自己定义,或者说由实现WebServer的各种软件和框架)来自动映射。
我们把静态资源文件存放在服务器的某个位置,如:
- D:/kkb/public/
同时我们去解析请求的 URL,只要 URL 上的路径符合某种规则(自定),如:
- /public/1.html
那么我们可以根据这种规则,利用 fs
去读取对应的文件,只需要按照 URL 去生成对应的真实文件路径即可:
// [file: app.js]// 首先通过 require 引入 http 模块
const http = require('http');
const fs = require('fs');// 创建一个 Server 对象
const server = http.createServer((req, res) => {const url = req.url;let resContent = '';// 针对不同url进行不同的处理if (url.startsWith('/public')) {// 真实文件存储的位置自己写的自己定,用别人写的就根据别人的规则定,原理一样// resContent = fs.readFileSync('D:/kkb' + url);resContent = fs.readFileSync('.' + url);} else {// 这里处理动态资源,以及其它一些情况if (url == '/now') {resContent = (new Date).toString();} else {resContent = '啥也没有';}}res.end(resContent);
});server.listen(8888, () => {console.log('服务已经启动了,http://127.0.0.1:8888');
});
头信息
头信息是每次请求和响应的时候所携带的一些非主体内容相关的信息,用于请求和接收方作为某种处理依据(但其本身并非主要内容),比如请求的时候所使用的代理(如浏览器,请求并不一定是浏览器发起,比如迅雷等下载软件也可以发送http请求)。作用类似写信(邮件)所填写的邮编、邮箱地址等非信件本身的信息。
由的头信息只能在请求中设置,有的只能在响应中设置,而有的双方都可以设置。
参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
Content-Type
设置发送的内容 MIME 类型
参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Type
MIME
参考:
https://baike.baidu.com/item/MIME/2900607
https://en.wikipedia.org/wiki/MIME
http://www.iana.org/assignments/media-types/media-types.xhtml
动态资源处理
许多时候,动态资源会相对复杂一些,有的时候需要根据业务产生一些数据,同时又会把这个数据进行一些包装(嵌入到HTML代码)中,如果每次都字符串拼接去做会比较麻烦:
- 拼接数据和html字符串毕竟麻烦,且容易出错。
- 逻辑处理很繁琐,同样也容易出错。
- 不容易维护,前端页面处理(html、css等)和后端(Node.js)代码混合。
- ……
模板引擎
把数据与某个模板文件(通常是类似HTML,但是又包含了一些特殊定义的语法的字符串/文件),进行结合,利用引擎(写好的方法)去对模板文件中的特殊语法(模板引擎定义语法 - 语法取决于具体模板引擎)进行解析,得到最终的 HTML 字符串。
Nunjucks
参考:
https://mozilla.github.io/nunjucks/
https://nunjucks.bootcss.com/
queryString
在 URL 中,除了路径部分,还有一个 query 部分(url 的 ?
后面的内容),称为:查询字符串(queryString),通常情况下,我们可以在请求的 URL 中通过路径 ?
后面加入一种特殊组织格式的数据携带一些数据,用于服务端进行一些额外的逻辑处理。
它的结构为使用 &
或者 ;
分割的键值对字符串,键值对的 键 与 值 使用 =
进行分隔,如:
http://kaikeba.com/items?order=asc&typeId=1
参考:
https://en.wikipedia.org/wiki/Query_string
Node.js 中的 queryString 模块
我们可以自己封装处理 queryString 的方法,也可以直接使用 Node.js 内置的 queryString
模块来处理。
参考:https://nodejs.org/dist/latest-v12.x/docs/api/querystring.html
请求方式
为了规范统一和语义化资源处理的行为,在定义了 URL 这种资源定位规范以外,还定义了一套动作,也称为请求方式(请求方法)
参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods
// 针对 POST 方式提交的数据进行单独处理
} else if (url == '/add' && req.method.toUpperCase() == 'POST') {let data = await new Promise(resolve => {let reqData = '';req.on('data', data => {console.log('data', data);reqData += data.toString();})req.on('end', () => {console.log('over');resolve(reqData);})})console.log('提交过来的数据是:', data);resContent = '提交成功';
}
Content-Type
同时,我们也可以通过提交过来的 Content-Type
来针对性的处理:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
注:
- 浏览器 GET 不支持提交正文
- queryString 属于 URL,与请求方式无关(任何方式的请求都可以携带 queryString)
工具
一些开发工具
- nodemon: https://www.npmjs.com/package/nodemon
// 127.0.0.1 => 本机网络地址,专门自己给自己打电话所使用的号码
// console.log('欢迎欢迎', window);// 首先通过 require 引入 http 模块
const http = require('http');// 创建一个 Server 对象,用来处理请求
const server = http.createServer((req, res) => {// 当有请求的时候,会在服务端控制台打印console.log('有人发送了一个请求');// console.log('req', req);// localhost => 127.0.0.1// req => http.IncomingMessage 对象:当前发送请求的客户端对象(提供保存了与当前请求的客户端相关信息)// res => http.ServerResponse 对象:提供了一个服务端向客户端进行响应一些方法// http: 非持久性链接,http目的是返回数据资源的,不在乎他的实时性,当当前这次请求完成以后,为了保证资源不被长久占用,为更多的请求提供服务// res.write('Hello');// 告诉客户端,我们的响应以及完成了,调用 end 方法res.end('hello');
});// server.on('request', () => {// console.log('有人发送了一个请求');
// });// 不要让程序退出,并且要监听一个网络端口
// 端口:把数据与具体的应用程序(比如当前这个server)进行绑定的一种机制
// server.listen(8888, '0.0.0.0');
server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
const http = require('http');const server = http.createServer((req, res) => {/*** http* 协议:做某件事情的一种规范和标准(约束)* 超文本传输协议:超文本在网络中传输的一种规范* tcp/ip: 数据传输规范*/console.log('有人发送了一个请求');// 虚拟路径,不是服务器中某个资源的真实路径// console.log('url', req.url);// 向客户端写入头信息let url = req.url;if (url === '/') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});res.end('<h1>欢迎来到开课吧</h1>');}if (url === '/login') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});res.end('<h1>登录页面</h1>');}
});server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
const http = require('http');const server = http.createServer( (req, res) => {let url = req.url;if (url === '/') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});res.end('<link href="css" rel="stylesheet" /><h1>欢迎来到开课吧</h1>');}if (url === '/css') {res.writeHead(200, 'ok', {'content-type': 'text/css; charset=utf-8'});res.end('body {color: red}');}if (url === '/login') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});res.end('<h1>登录页面</h1>');}
} );server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
const http = require('http');
const fs = require('fs');const server = http.createServer( (req, res) => {let url = req.url;// 我们把这种资源(css,js、html)保存在一个外部文件中,这样方便我们管理,编写,以及统一处理,然后我们会这种文件定义一套访问规则let content = '';if (url === '/') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});content = fs.readFileSync('./public/dahai.html');res.end(content);}if (url === '/css') {res.writeHead(200, 'ok', {'content-type': 'text/css; charset=utf-8'});content = fs.readFileSync('./public/css.css');res.end(content);}if (url === '/js') {res.writeHead(200, 'ok', {'content-type': 'application/javascript; charset=utf-8'});content = fs.readFileSync('./public/diange.js');res.end(content);}} );server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
const http = require('http');
const fs = require('fs');const server = http.createServer( (req, res) => {let url = req.url;// 我们把这种资源(css,js、html)保存在一个外部文件中,这样方便我们管理,编写,以及统一处理,然后我们会这种文件定义一套访问规则/*** url /css.css => fs => public/css.css* url /dahai.html => fs => public/dahai.html* url /diange.js => fs => public/diange.js*/let content = '';let filePath = './public' + url;console.log('url', url, filePath);if (url.includes('.ico')) {res.end('');} else {// 在不修改文件的基础上,访问的内容保持不变的资源 - 静态资源res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});content = fs.readFileSync(filePath);res.end(content);}
} );server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
const http = require('http');
const fs = require('fs');const server = http.createServer( (req, res) => {let url = req.url;// 我们把这种资源(css,js、html)保存在一个外部文件中,这样方便我们管理,编写,以及统一处理,然后我们会这种文件定义一套访问规则/*** url /css.css => fs => public/css.css* url /dahai.html => fs => public/dahai.html* url /diange.js => fs => public/diange.js*/let content = '';// let filePath = './public' + url;// console.log('url', url, filePath);if (url.includes('.ico')) {res.end('');} else {// 把动态资源和静态资源的访问规则制定一下,加以区别if (url.startsWith('/public')) {let filePath = '.' + url;res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});content = fs.readFileSync(filePath);res.end(content);} else {// 动态资源的url一般没有太多的规则,所以一般都需要一个一个的定义if (url === '/getDateTime') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});res.end(new Date().toString());}} }
} );server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
const http = require('http');
const fs = require('fs');
const mime = require('./mime.json');
// console.log('mime', mime);const server = http.createServer( (req, res) => {let url = req.url;// 我们把这种资源(css,js、html)保存在一个外部文件中,这样方便我们管理,编写,以及统一处理,然后我们会这种文件定义一套访问规则/*** url /css.css => fs => public/css.css* url /dahai.html => fs => public/dahai.html* url /diange.js => fs => public/diange.js*/let content = '';// let filePath = './public' + url;// console.log('url', url, filePath);if (url.includes('.ico')) {res.end('');} else {// 把动态资源和静态资源的访问规则制定一下,加以区别if (url.startsWith('/public')) {let filePath = '.' + url;// 因为静态资源的种类比较多,所以我们需要为不同类型的静态资源返回不同类型 content-type// 需要根据请求的url的特征(一般利用文件的后缀名)// 1、获取当前请求的url后缀let lastPointIndex = filePath.lastIndexOf('.');// 2、根据 lastPointIndex 截取这个点后面的内容let suffix = filePath.substring(lastPointIndex);// console.log('suffix', suffix);// 通过 suffix 获取对应的 mimelet mimeType = mime[suffix];// console.log('mimeType', mimeType);res.writeHead(200, 'ok', {'content-type': mimeType + '; charset=utf-8'});content = fs.readFileSync(filePath);res.end(content);} else {// 动态资源的url一般没有太多的规则,所以一般都需要一个一个的定义if (url === '/getDateTime') {res.writeHead(200, 'ok', {'content-type': 'text/html; charset=utf-8'});res.end(new Date().toString());}}}
} );server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
练习要求
- 1、使用node.js的http模块搭建一个webserver项目
- 1-1、端口8888
- 2、访问 http://localhost:8888/public/index.html 返回 public 目录下的 index.html 内容
- 2-1、项目目录下创建一个 public 目录
- 2-2、public 下创建一个 index.html 文件(文件内容不限制)
- 3、访问 http://localhost:8888/quote 随机返回一句毒鸡汤
毒鸡汤范文
const quotes = [
‘虽然我个子矮,但我发际线高啊!’,
‘有些事情做不完,就留到明天做吧。运气好的话,明天死了就不用做了。’,
‘善良没用,你得漂亮。’,
‘好好活下去 每天都有新打击。’,
‘活着的时候把自己搞得好看一点,这样你就不会死得太难看。’,
‘世上无难事 只要肯放弃。’,
‘加油,你是最胖的!’
];
// app.js
const http = require('http');
const fs = require('fs');
const mime = require('./mime.json');const quotes = ['虽然我个子矮,但我发际线高啊!','有些事情做不完,就留到明天做吧。运气好的话,明天死了就不用做了。','善良没用,你得漂亮。','好好活下去 每天都有新打击。','活着的时候把自己搞得好看一点,这样你就不会死得太难看。','世上无难事 只要肯放弃。','加油,你是最胖的!'
];const server = http.createServer((req, res) => {let url = req.url;let statusCode = 200;let content = '';let mimeType = 'text/html';// 静态资源访问if (url.startsWith('/public')) {let filePath = '.' + url;try {let lastPointIndex = filePath.lastIndexOf('.');let suffix = filePath.substring(lastPointIndex);mimeType = mime[suffix];content = fs.readFileSync(filePath);} catch (e) {statusCode = 400;content = fs.readFileSync('./public/404.html');}res.writeHead(statusCode, {'content-type': `${mimeType};charset="utf-8"`});res.end(content);} else {if (url === '/quote') {res.writeHead(statusCode, {'content-type': `${mimeType};charset="utf-8"`});content = quotes.sort(() => Math.random() - .5)[0];res.end(content);}}});server.listen(8888, () => {console.log(`服务器启动成功:http://localhost:8888`);
});
<!-- /public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>hello world</h1>
</body>
</html>
<!-- /public/404.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>页面不存在!</h1>
</body>
</html>
mime.json
{ ".323":"text/h323" ,".3gp":"video/3gpp" ,".aab":"application/x-authoware-bin" ,".aam":"application/x-authoware-map" ,".aas":"application/x-authoware-seg" ,".acx":"application/internet-property-stream" ,".ai":"application/postscript" ,".aif":"audio/x-aiff" ,".aifc":"audio/x-aiff" ,".aiff":"audio/x-aiff" ,".als":"audio/X-Alpha5" ,".amc":"application/x-mpeg" ,".ani":"application/octet-stream" ,".apk":"application/vnd.android.package-archive" ,".asc":"text/plain" ,".asd":"application/astound" ,".asf":"video/x-ms-asf" ,".asn":"application/astound" ,".asp":"application/x-asap" ,".asr":"video/x-ms-asf" ,".asx":"video/x-ms-asf" ,".au":"audio/basic" ,".avb":"application/octet-stream" ,".avi":"video/x-msvideo" ,".awb":"audio/amr-wb" ,".axs":"application/olescript" ,".bas":"text/plain" ,".bcpio":"application/x-bcpio" ,".bin ":"application/octet-stream" ,".bld":"application/bld" ,".bld2":"application/bld2" ,".bmp":"image/bmp" ,".bpk":"application/octet-stream" ,".bz2":"application/x-bzip2" ,".c":"text/plain" ,".cal":"image/x-cals" ,".cat":"application/vnd.ms-pkiseccat" ,".ccn":"application/x-cnc" ,".cco":"application/x-cocoa" ,".cdf":"application/x-cdf" ,".cer":"application/x-x509-ca-cert" ,".cgi":"magnus-internal/cgi" ,".chat":"application/x-chat" ,".class":"application/octet-stream" ,".clp":"application/x-msclip" ,".cmx":"image/x-cmx" ,".co":"application/x-cult3d-object" ,".cod":"image/cis-cod" ,".conf":"text/plain" ,".cpio":"application/x-cpio" ,".cpp":"text/plain" ,".cpt":"application/mac-compactpro" ,".crd":"application/x-mscardfile" ,".crl":"application/pkix-crl" ,".crt":"application/x-x509-ca-cert" ,".csh":"application/x-csh" ,".csm":"chemical/x-csml" ,".csml":"chemical/x-csml" ,".css":"text/css" ,".cur":"application/octet-stream" ,".dcm":"x-lml/x-evm" ,".dcr":"application/x-director" ,".dcx":"image/x-dcx" ,".der":"application/x-x509-ca-cert" ,".dhtml":"text/html" ,".dir":"application/x-director" ,".dll":"application/x-msdownload" ,".dmg":"application/octet-stream" ,".dms":"application/octet-stream" ,".doc":"application/msword" ,".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document" ,".dot":"application/msword" ,".dvi":"application/x-dvi" ,".dwf":"drawing/x-dwf" ,".dwg":"application/x-autocad" ,".dxf":"application/x-autocad" ,".dxr":"application/x-director" ,".ebk":"application/x-expandedbook" ,".emb":"chemical/x-embl-dl-nucleotide" ,".embl":"chemical/x-embl-dl-nucleotide" ,".eps":"application/postscript" ,".epub":"application/epub+zip" ,".eri":"image/x-eri" ,".es":"audio/echospeech" ,".esl":"audio/echospeech" ,".etc":"application/x-earthtime" ,".etx":"text/x-setext" ,".evm":"x-lml/x-evm" ,".evy":"application/envoy" ,".exe":"application/octet-stream" ,".fh4":"image/x-freehand" ,".fh5":"image/x-freehand" ,".fhc":"image/x-freehand" ,".fif":"application/fractals" ,".flr":"x-world/x-vrml" ,".flv":"flv-application/octet-stream" ,".fm":"application/x-maker" ,".fpx":"image/x-fpx" ,".fvi":"video/isivideo" ,".gau":"chemical/x-gaussian-input" ,".gca":"application/x-gca-compressed" ,".gdb":"x-lml/x-gdb" ,".gif":"image/gif" ,".gps":"application/x-gps" ,".gtar":"application/x-gtar" ,".gz":"application/x-gzip" ,".h":"text/plain" ,".hdf":"application/x-hdf" ,".hdm":"text/x-hdml" ,".hdml":"text/x-hdml" ,".hlp":"application/winhlp" ,".hqx":"application/mac-binhex40" ,".hta":"application/hta" ,".htc":"text/x-component" ,".htm":"text/html" ,".html":"text/html" ,".hts":"text/html" ,".htt":"text/webviewhtml" ,".ice":"x-conference/x-cooltalk" ,".ico":"image/x-icon" ,".ief":"image/ief" ,".ifm":"image/gif" ,".ifs":"image/ifs" ,".iii":"application/x-iphone" ,".imy":"audio/melody" ,".ins":"application/x-internet-signup" ,".ips":"application/x-ipscript" ,".ipx":"application/x-ipix" ,".isp":"application/x-internet-signup" ,".it":"audio/x-mod" ,".itz":"audio/x-mod" ,".ivr":"i-world/i-vrml" ,".j2k":"image/j2k" ,".jad":"text/vnd.sun.j2me.app-descriptor" ,".jam":"application/x-jam" ,".jar":"application/java-archive" ,".java":"text/plain" ,".jfif":"image/pipeg" ,".jnlp":"application/x-java-jnlp-file" ,".jpe":"image/jpeg" ,".jpeg":"image/jpeg" ,".jpg":"image/jpeg" ,".jpz":"image/jpeg" ,".js":"application/x-javascript" ,".jwc":"application/jwc" ,".kjx":"application/x-kjx" ,".lak":"x-lml/x-lak" ,".latex":"application/x-latex" ,".lcc":"application/fastman" ,".lcl":"application/x-digitalloca" ,".lcr":"application/x-digitalloca" ,".lgh":"application/lgh" ,".lha":"application/octet-stream" ,".lml":"x-lml/x-lml" ,".lmlpack":"x-lml/x-lmlpack" ,".log":"text/plain" ,".lsf":"video/x-la-asf" ,".lsx":"video/x-la-asf" ,".lzh":"application/octet-stream" ,".m13":"application/x-msmediaview" ,".m14":"application/x-msmediaview" ,".m15":"audio/x-mod" ,".m3u":"audio/x-mpegurl" ,".m3url":"audio/x-mpegurl" ,".m4a":"audio/mp4a-latm" ,".m4b":"audio/mp4a-latm" ,".m4p":"audio/mp4a-latm" ,".m4u":"video/vnd.mpegurl" ,".m4v":"video/x-m4v" ,".ma1":"audio/ma1" ,".ma2":"audio/ma2" ,".ma3":"audio/ma3" ,".ma5":"audio/ma5" ,".man":"application/x-troff-man" ,".map":"magnus-internal/imagemap" ,".mbd":"application/mbedlet" ,".mct":"application/x-mascot" ,".mdb":"application/x-msaccess" ,".mdz":"audio/x-mod" ,".me":"application/x-troff-me" ,".mel":"text/x-vmel" ,".mht":"message/rfc822" ,".mhtml":"message/rfc822" ,".mi":"application/x-mif" ,".mid":"audio/mid" ,".midi":"audio/midi" ,".mif":"application/x-mif" ,".mil":"image/x-cals" ,".mio":"audio/x-mio" ,".mmf":"application/x-skt-lbs" ,".mng":"video/x-mng" ,".mny":"application/x-msmoney" ,".moc":"application/x-mocha" ,".mocha":"application/x-mocha" ,".mod":"audio/x-mod" ,".mof":"application/x-yumekara" ,".mol":"chemical/x-mdl-molfile" ,".mop":"chemical/x-mopac-input" ,".mov":"video/quicktime" ,".movie":"video/x-sgi-movie" ,".mp2":"video/mpeg" ,".mp3":"audio/mpeg" ,".mp4":"video/mp4" ,".mpa":"video/mpeg" ,".mpc":"application/vnd.mpohun.certificate" ,".mpe":"video/mpeg" ,".mpeg":"video/mpeg" ,".mpg":"video/mpeg" ,".mpg4":"video/mp4" ,".mpga":"audio/mpeg" ,".mpn":"application/vnd.mophun.application" ,".mpp":"application/vnd.ms-project" ,".mps":"application/x-mapserver" ,".mpv2":"video/mpeg" ,".mrl":"text/x-mrml" ,".mrm":"application/x-mrm" ,".ms":"application/x-troff-ms" ,".msg":"application/vnd.ms-outlook" ,".mts":"application/metastream" ,".mtx":"application/metastream" ,".mtz":"application/metastream" ,".mvb":"application/x-msmediaview" ,".mzv":"application/metastream" ,".nar":"application/zip" ,".nbmp":"image/nbmp" ,".nc":"application/x-netcdf" ,".ndb":"x-lml/x-ndb" ,".ndwn":"application/ndwn" ,".nif":"application/x-nif" ,".nmz":"application/x-scream" ,".nokia-op-logo":"image/vnd.nok-oplogo-color" ,".npx":"application/x-netfpx" ,".nsnd":"audio/nsnd" ,".nva":"application/x-neva1" ,".nws":"message/rfc822" ,".oda":"application/oda" ,".ogg":"audio/ogg" ,".oom":"application/x-AtlasMate-Plugin" ,".p10":"application/pkcs10" ,".p12":"application/x-pkcs12" ,".p7b":"application/x-pkcs7-certificates" ,".p7c":"application/x-pkcs7-mime" ,".p7m":"application/x-pkcs7-mime" ,".p7r":"application/x-pkcs7-certreqresp" ,".p7s":"application/x-pkcs7-signature" ,".pac":"audio/x-pac" ,".pae":"audio/x-epac" ,".pan":"application/x-pan" ,".pbm":"image/x-portable-bitmap" ,".pcx":"image/x-pcx" ,".pda":"image/x-pda" ,".pdb":"chemical/x-pdb" ,".pdf":"application/pdf" ,".pfr":"application/font-tdpfr" ,".pfx":"application/x-pkcs12" ,".pgm":"image/x-portable-graymap" ,".pict":"image/x-pict" ,".pko":"application/ynd.ms-pkipko" ,".pm":"application/x-perl" ,".pma":"application/x-perfmon" ,".pmc":"application/x-perfmon" ,".pmd":"application/x-pmd" ,".pml":"application/x-perfmon" ,".pmr":"application/x-perfmon" ,".pmw":"application/x-perfmon" ,".png":"image/png" ,".pnm":"image/x-portable-anymap" ,".pnz":"image/png" ,".pot,":"application/vnd.ms-powerpoint" ,".ppm":"image/x-portable-pixmap" ,".pps":"application/vnd.ms-powerpoint" ,".ppt":"application/vnd.ms-powerpoint" ,".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation" ,".pqf":"application/x-cprplayer" ,".pqi":"application/cprplayer" ,".prc":"application/x-prc" ,".prf":"application/pics-rules" ,".prop":"text/plain" ,".proxy":"application/x-ns-proxy-autoconfig" ,".ps":"application/postscript" ,".ptlk":"application/listenup" ,".pub":"application/x-mspublisher" ,".pvx":"video/x-pv-pvx" ,".qcp":"audio/vnd.qcelp" ,".qt":"video/quicktime" ,".qti":"image/x-quicktime" ,".qtif":"image/x-quicktime" ,".r3t":"text/vnd.rn-realtext3d" ,".ra":"audio/x-pn-realaudio" ,".ram":"audio/x-pn-realaudio" ,".rar":"application/octet-stream" ,".ras":"image/x-cmu-raster" ,".rc":"text/plain" ,".rdf":"application/rdf+xml" ,".rf":"image/vnd.rn-realflash" ,".rgb":"image/x-rgb" ,".rlf":"application/x-richlink" ,".rm":"audio/x-pn-realaudio" ,".rmf":"audio/x-rmf" ,".rmi":"audio/mid" ,".rmm":"audio/x-pn-realaudio" ,".rmvb":"audio/x-pn-realaudio" ,".rnx":"application/vnd.rn-realplayer" ,".roff":"application/x-troff" ,".rp":"image/vnd.rn-realpix" ,".rpm":"audio/x-pn-realaudio-plugin" ,".rt":"text/vnd.rn-realtext" ,".rte":"x-lml/x-gps" ,".rtf":"application/rtf" ,".rtg":"application/metastream" ,".rtx":"text/richtext" ,".rv":"video/vnd.rn-realvideo" ,".rwc":"application/x-rogerwilco" ,".s3m":"audio/x-mod" ,".s3z":"audio/x-mod" ,".sca":"application/x-supercard" ,".scd":"application/x-msschedule" ,".sct":"text/scriptlet" ,".sdf":"application/e-score" ,".sea":"application/x-stuffit" ,".setpay":"application/set-payment-initiation" ,".setreg":"application/set-registration-initiation" ,".sgm":"text/x-sgml" ,".sgml":"text/x-sgml" ,".sh":"application/x-sh" ,".shar":"application/x-shar" ,".shtml":"magnus-internal/parsed-html" ,".shw":"application/presentations" ,".si6":"image/si6" ,".si7":"image/vnd.stiwap.sis" ,".si9":"image/vnd.lgtwap.sis" ,".sis":"application/vnd.symbian.install" ,".sit":"application/x-stuffit" ,".skd":"application/x-Koan" ,".skm":"application/x-Koan" ,".skp":"application/x-Koan" ,".skt":"application/x-Koan" ,".slc":"application/x-salsa" ,".smd":"audio/x-smd" ,".smi":"application/smil" ,".smil":"application/smil" ,".smp":"application/studiom" ,".smz":"audio/x-smd" ,".snd":"audio/basic" ,".spc":"application/x-pkcs7-certificates" ,".spl":"application/futuresplash" ,".spr":"application/x-sprite" ,".sprite":"application/x-sprite" ,".sdp":"application/sdp" ,".spt":"application/x-spt" ,".src":"application/x-wais-source" ,".sst":"application/vnd.ms-pkicertstore" ,".stk":"application/hyperstudio" ,".stl":"application/vnd.ms-pkistl" ,".stm":"text/html" ,".svg":"image/svg+xml" ,".sv4cpio":"application/x-sv4cpio" ,".sv4crc":"application/x-sv4crc" ,".svf":"image/vnd" ,".svg":"image/svg+xml" ,".svh":"image/svh" ,".svr":"x-world/x-svr" ,".swf":"application/x-shockwave-flash" ,".swfl":"application/x-shockwave-flash" ,".t":"application/x-troff" ,".tad":"application/octet-stream" ,".talk":"text/x-speech" ,".tar":"application/x-tar" ,".taz":"application/x-tar" ,".tbp":"application/x-timbuktu" ,".tbt":"application/x-timbuktu" ,".tcl":"application/x-tcl" ,".tex":"application/x-tex" ,".texi":"application/x-texinfo" ,".texinfo":"application/x-texinfo" ,".tgz":"application/x-compressed" ,".thm":"application/vnd.eri.thm" ,".tif":"image/tiff" ,".tiff":"image/tiff" ,".tki":"application/x-tkined" ,".tkined":"application/x-tkined" ,".toc":"application/toc" ,".toy":"image/toy" ,".tr":"application/x-troff" ,".trk":"x-lml/x-gps" ,".trm":"application/x-msterminal" ,".tsi":"audio/tsplayer" ,".tsp":"application/dsptype" ,".tsv":"text/tab-separated-values" ,".ttf":"application/octet-stream" ,".ttz":"application/t-time" ,".txt":"text/plain" ,".uls":"text/iuls" ,".ult":"audio/x-mod" ,".ustar":"application/x-ustar" ,".uu":"application/x-uuencode" ,".uue":"application/x-uuencode" ,".vcd":"application/x-cdlink" ,".vcf":"text/x-vcard" ,".vdo":"video/vdo" ,".vib":"audio/vib" ,".viv":"video/vivo" ,".vivo":"video/vivo" ,".vmd":"application/vocaltec-media-desc" ,".vmf":"application/vocaltec-media-file" ,".vmi":"application/x-dreamcast-vms-info" ,".vms":"application/x-dreamcast-vms" ,".vox":"audio/voxware" ,".vqe":"audio/x-twinvq-plugin" ,".vqf":"audio/x-twinvq" ,".vql":"audio/x-twinvq" ,".vre":"x-world/x-vream" ,".vrml":"x-world/x-vrml" ,".vrt":"x-world/x-vrt" ,".vrw":"x-world/x-vream" ,".vts":"workbook/formulaone" ,".wav":"audio/x-wav" ,".wax":"audio/x-ms-wax" ,".wbmp":"image/vnd.wap.wbmp" ,".wcm":"application/vnd.ms-works" ,".wdb":"application/vnd.ms-works" ,".web":"application/vnd.xara" ,".wi":"image/wavelet" ,".wis":"application/x-InstallShield" ,".wks":"application/vnd.ms-works" ,".wm":"video/x-ms-wm" ,".wma":"audio/x-ms-wma" ,".wmd":"application/x-ms-wmd" ,".wmf":"application/x-msmetafile" ,".wml":"text/vnd.wap.wml" ,".wmlc":"application/vnd.wap.wmlc" ,".wmls":"text/vnd.wap.wmlscript" ,".wmlsc":"application/vnd.wap.wmlscriptc" ,".wmlscript":"text/vnd.wap.wmlscript" ,".wmv":"audio/x-ms-wmv" ,".wmx":"video/x-ms-wmx" ,".wmz":"application/x-ms-wmz" ,".wpng":"image/x-up-wpng" ,".wps":"application/vnd.ms-works" ,".wpt":"x-lml/x-gps" ,".wri":"application/x-mswrite" ,".wrl":"x-world/x-vrml" ,".wrz":"x-world/x-vrml" ,".ws":"text/vnd.wap.wmlscript" ,".wsc":"application/vnd.wap.wmlscriptc" ,".wv":"video/wavelet" ,".wvx":"video/x-ms-wvx" ,".wxl":"application/x-wxl" ,".x-gzip":"application/x-gzip" ,".xaf":"x-world/x-vrml" ,".xar":"application/vnd.xara" ,".xbm":"image/x-xbitmap" ,".xdm":"application/x-xdma" ,".xdma":"application/x-xdma" ,".xdw":"application/vnd.fujixerox.docuworks" ,".xht":"application/xhtml+xml" ,".xhtm":"application/xhtml+xml" ,".xhtml":"application/xhtml+xml" ,".xla":"application/vnd.ms-excel" ,".xlc":"application/vnd.ms-excel" ,".xll":"application/x-excel" ,".xlm":"application/vnd.ms-excel" ,".xls":"application/vnd.ms-excel" ,".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ,".xlt":"application/vnd.ms-excel" ,".xlw":"application/vnd.ms-excel" ,".xm":"audio/x-mod" ,".xml":"text/plain",".xml":"application/xml",".xmz":"audio/x-mod" ,".xof":"x-world/x-vrml" ,".xpi":"application/x-xpinstall" ,".xpm":"image/x-xpixmap" ,".xsit":"text/xml" ,".xsl":"text/xml" ,".xul":"text/xul" ,".xwd":"image/x-xwindowdump" ,".xyz":"chemical/x-pdb" ,".yz1":"application/x-yz1" ,".z":"application/x-compress" ,".zac":"application/x-zaurus-zac" ,".zip":"application/zip" ,".json":"application/json"
}
nodejs01——安装及使用、服务端及客户端、commonjs规范、fs模块的使用(文件操作及目录操作)、stream、buffer、WebServer、端口、动态资源及静态资源、头信息、请求方式相关推荐
- CARLA 笔记(02)— Ubuntu 安装 CARLA(服务端、客户端、安装 miniconda、创建虚拟环境、更换 pip 源、生成交通流、人工控制车辆按键)
https://carla.readthedocs.io/en/0.9.13/start_quickstart/ 1. 预置条件 Ubuntu 18.04 CARLA 0.9.13 8 GB 以上显卡 ...
- 【windows】实战部署一(安装)SVNserver服务端+SVNclient客户端
1.环境准备 下载SVNserver https://www.visualsvn.com/server/download/ 下载SVNclient https://tortoisesvn.net/do ...
- 网络启动安装linux客户机nfs设置,NFS服务端和客户端安装配置
一 NFS介绍 NFS用的比较多,但是更新没有想象的那么快,Nginx一年要迭代很多个版本,而NFS最新版本4.1是2010年更新的,到目前为止还没有更新过,但这并不影响NFS使用的广泛性 RPC协 ...
- linux远程日志rsyslog服务端和客户端安装(亲测)--自定义接收日志格式
linux远程日志rsyslog服务端和客户端安装 用rsyslog的缘由: 1.防止系统崩溃无法获取系统日志分享崩溃原因,用rsyslog可以把日志传输到远程的日志服务器上 2.使用rsyslo ...
- 无盘服务器 安装客户机程序,顺网云服务端和客户端安装
在维护云网站或 APP 端,进行平台账号注册: 访问维护云平台注册页面 访问维护云 App 下载界面 新用户注册完成,系统即自动为您定制专属安装包. 服务端安装 双击服务端 exe 安装程序,输入网吧 ...
- (SVN笔记)SVN服务端+SVN客户端Tortoise——安装配置
目录 1.前言 2.官网下载SVN服务端1.14.1 3.安装SVN服务端Server 4.官网下载SVN客户端Tortoise4.3.4 5.安装Tortoise 6.验证Tortoise安装 7. ...
- SVN服务端和客户端的安装与搭建
SVN简介 SVN全名Subversion,是一个开源的版本控制系统.SVN与CVS一样,是一个跨平台的软件,支持大多数常见的操作系统,SVN拥有CVS的大部分特征,并且在CVS的基础上有更强的扩展. ...
- SVN服务端、客户端安装配置和填坑
一.svn服务端和客户端安装: 1.安装程序: 服务端程序:Setup-Subversion-1.8.17.msi 客户端程序:TortoiseSVN-1.9.7.27907-x64-svn-1.9. ...
- wireguard服务端和客户端的安装
1.说明 wireguard是开源代理软件,包括服务端和客户端.这里为了测试wireguard的window客户端能否代理DNS.ICMP.以及是否需要管理员权限. 关于window客户端使用了win ...
最新文章
- 爬虫之requests模块发送带header的请求
- matplot 绘图总结
- 再写单链表(不带头单链表)
- 通俗理解“Schmidt正交化”和“正交矩阵” 此博文包含图片	(2015-05-19 09:50:47) 施密特正交化在空间上是不断建立垂直于原次维空间的新向量的过程。 如图β2垂直于β1(1维)
- python安装selenium报错_新手用Python运行selenium的常见问题
- 第一章:x264视频制作meGUI工具下载
- 计算机c盘如何扩容,C盘满想换SSD遇涨价?教你C盘扩容技巧
- PHP 简单开发实例
- php工程师的学习之道以及需要掌握的知识体系
- 通过ssh远程启动linux上的Qt界面程序
- 三防产品外观设计要点
- 装修店铺营销活动策划?
- 用ChatGPT实现变现的多种方法
- 基于GEE洪水发生前后的分析
- Debian下Apache2安装与设置 一 ZT
- UVa 207 - PGA Tour Prize Money(模拟)
- php 关键词生成,全自动无限生成关键词页面(黑帽SEO优化终极方法)
- shell练习Day1
- 工作的未来是DAO,收入的未来是「X-to-earn」 |链捕手
- 如何为您的在线业务设置和使用YouTube
热门文章
- MATLAB基础编程(004-01)在不同初速度和重力加速度下的的动态抛物运动绘图
- Redis-使用和原理
- iOS 自定义相机,拍照旋转
- 设计模式(二)——UML类图怎么画
- C++中的 .h 和 .cpp 详解
- 微信开发 现金红包、裂变红包、企业付款
- #include中用双引号和用尖括号括起来头文件的区别
- 公众号自动回复不生效php,php,微信公众平台开发者_微信公众号开发者自动回复设置没反应,php,微信公众平台开发者 - phpStudy...
- Byval和ByRef
- 论作业成本法在中小酒店的应用中存在的问题及对策