nodejs的安装及使用
服务端及客户端
commonjs规范
fs模块的使用(文件操作及目录操作)
stream
buffer
//
Node.js 诞生于2009年,Node.js采用C++语言编写而成,是 一个Javascript的运行环境。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境 ,让JavaScript的运行脱离浏览器端,可以使用JavaScript语言 书写服务器端代码。
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, // tcpmux
7, // echo
9, // discard
11, // systat
13, // daytime
15, // netstat
17, // qotd
19, // chargen
20, // ftp data
21, // ftp access
22, // ssh
23, // telnet
25, // smtp
37, // time
42, // name
43, // nicname
53, // domain
77, // priv-rjs
79, // finger
87, // ttylink
95, // supdup
101, // hostriame
102, // iso-tsap
103, // gppitnp
104, // acr-nema
109, // pop2
110, // pop3
111, // sunrpc
113, // auth
115, // sftp
117, // uucp-path
119, // nntp
123, // NTP
135, // loc-srv /epmap
139, // netbios
143, // imap2
179, // BGP
389, // ldap
465, // smtp+ssl
512, // print / exec
513, // login
514, // shell
515, // printer
526, // tempo
530, // courier
531, // chat
532, // netnews
540, // uucp
556, // remotefs
563, // nntp+ssl
587, // stmp?
601, // ??
636, // ldap+ssl
993, // ldap+ssl
995, // pop3+ssl
2049, // nfs
3659, // apple-sasl / PasswordServer
4045, // lockd
6000, // X11
6665, // 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;
引入文件夹形式模块
require("./aModuledir"); //必须加"./"
aModuleDir里的index.js文件,会自动查找文件夹下的index.js文件执行
console.log("我是aModule模块文件夹");
{
"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(Node Package Manager) 官网的地址是 npm官网
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("复制成功!");
})
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创建
// 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 流;
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("写入成功");
// })
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 本质上就是一个软件,一个用来处理网络数据交互的程序,它可以用任何具备网络编程的语言来实现,如:c、c++、java,python,php 等,我们前面介绍的 Node.js 也可以。
Node.js 中已经内置提供了一个模块: http
,这个模块就提供了实现 http 所需要的 API:
https://nodejs.org/dist/latest-v12.x/docs/api/http.html
我们要创建一个 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
当服务启动成功以后,我们可以监听 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
事件回调函数中会自动传入两个参数,供我们进行后续的业务逻辑调用:
一个 Node.js 封装好的对象,与当前请求的客户端相关信息(客户端请求提交的数据,IP等)和方法都是通过该对象来完成。
一些常用属性和方法:
也是一个 Node.js 封装好的对象,提供了服务端信息和方法,比如向客户端发送数据的方法就由该对象提供。
一些常用的属性和方法:(write、end、setHeader、statusCode、statusMessage、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
也称为: 统一资源定位符(Uniform Resource Locator)
。
参考:
每一个互联网中的资源(资源可以是一段HTML字符串、HTML文件、CSS文件、JS文件、图片、视频、音频……)都会通过一个 URL
来与之对应,但是这种对应关系需要程序(WebServer)来实现。比如:http://kaikeba.com/js/hello 这个 URL 在找到 kaikeba.com 这个主机(服务器)以后,/js/hello 这个虚拟的 URL 路径会返回对应的内容是什么,它可以直接返回一个字符串,也可以返回一个服务器在某个地方存储的文件,也也也可以是这个服务器去另外一个主机上读取的内容。
我们可以通过分析每次请求的 url
来获取当前客户端要请求的资源。
// [file: app.js]
// 首先通过 require 引入 http 模块
const http = require('http');
// 创建一个 Server 对象
const server = http.createServer((req, res) => {
// 当前请求的 url
console.log('req.url', req.url);
});
server.listen(8888, () => {
console.log('服务已经启动了,http://127.0.0.1:8888');
});
根据不同的请求 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');
});
许多时候,我们会把资源简单的划分成:
相对不变的内容(除非你修改了它的内容),类似程序中的 变量与常量。
比如前面 / 、/kkb.html 以及 最后那个 啥也没有,就是静态内容,除非你去修改内容本身,否则访问对应的 URL ,返回的内容永远不变。
与静态资源不同,同一个 URL 返回的内容并不固定,比如访问 /now 这个 URL,即使不做任何修改,你就有可能得到不一样的结果,这就是动态资源。
通常,我们的 WebServer 会提供各种静态资源(html代码、css代码、js代码、图片……),而这些资源我们又通常会通过文件的方式存储在某个地方。为了批量处理这种资源与 URL 的对应关系,我们会根据某种规则(规则自己定义,或者说由实现WebServer的各种软件和框架)来自动映射。
我们把静态资源文件存放在服务器的某个位置,如:
同时我们去解析请求的 URL,只要 URL 上的路径符合某种规则(自定),如:
那么我们可以根据这种规则,利用 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
设置发送的内容 MIME 类型
参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Type
参考:
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 字符串。
参考:
https://mozilla.github.io/nunjucks/
https://nunjucks.bootcss.com/
在 URL 中,除了路径部分,还有一个 query 部分(url 的 ?
后面的内容),称为:查询字符串(queryString),通常情况下,我们可以在请求的 URL 中通过路径 ?
后面加入一种特殊组织格式的数据携带一些数据,用于服务端进行一些额外的逻辑处理。
它的结构为使用 &
或者 ;
分割的键值对字符串,键值对的 键 与 值 使用 =
进行分隔,如:
http://kaikeba.com/items?order=asc&typeId=1
参考:
https://en.wikipedia.org/wiki/Query_string
我们可以自己封装处理 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
来针对性的处理:
注:
- 浏览器 GET 不支持提交正文
- queryString 属于 URL,与请求方式无关(任何方式的请求都可以携带 queryString)
一些开发工具
// 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('欢迎来到开课吧
');
}
if (url === '/login') {
res.writeHead(200, 'ok', {
'content-type': 'text/html; charset=utf-8'
});
res.end('登录页面
');
}
});
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('欢迎来到开课吧
');
}
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('登录页面
');
}
} );
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 获取对应的 mime
let 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`);
});
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`);
});
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<h1>hello worldh1>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
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"
}