前言

又来写点了,之前玩物丧志,然后跳槽,搬家,安顿,比较折腾了,没怎么学习和记笔记,哈哈哈哈


Node 原生

创建一个服务:Hello Node.js

首先起一个简单的服务,新建一个 js文件,写入以下命令,并用 node xx.js 运行起来,之后在浏览器中访问 本地 3000 端口。

1
2
3
4
5
6
7
8
// 导入内置模块 http
const http = require("http");
// 创建服务
const server = http.createServer((req, res) => {
res.end("hello Node.js");
});
// 启动服务,监听 3000 端口
server.listen(3000);

支持中文:设置 setHeader

如果我返回一些中文,之后页面会出现如下乱码

1
2
3
4
5
const http = require("http");
const server = http.createServer((req, res) => {
res.end("你好 Node.js");
});
server.listen(3000);

页面出现乱码:Mac
在这里插入图片描述
windows 的页面可能是这样的

1
2
// 页面
浣犲ソ Node.js

这是因为我们没有设置返回的文字编码,解决的办法就是 添加页面文字编码

1
2
3
4
5
6
const http = require("http");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8"); // 添加页面文字编码
res.end("你好 Node.js");
});
server.listen(3000);

如何判断路由:req.url

可以通过 req.url 判断用户访问的那个地址,req.url 是用户在地址栏中输入的端口号后面的字符串,栗子:http://localhost:3000/index 或者是 http://localhost:3000/song

req.url 也会带 ? 后面的参数,比方说 http://localhost:3000/song?name=周杰伦 这个时候 req.url 就等于 /song?name=周杰伦 了。

1
2
3
4
5
6
7
8
9
10
11
const http = require("http");
const server = http.createServer((req, res) => {
let url = req.url;
res.setHeader("content-type", "text/html;charset=utf-8");
if (url === "/" || url === "/index") {
res.end("主页");
} else {
res.end("其他页面");
}
});
server.listen(3000);

内置模块 url

那这样的话就会出现问题,路由会匹配不到的,这时候我们就要想如何拿到不带参数的路由名称

这里有个新的内置模块 url 他会帮你解析一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const http = require("http");
const url = require("url");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8");
let reqUrl = req.url;
let realUrl = url.parse(reqUrl); // 解析 url,可以打印一下 realUrl 查看
console.log(realUrl);
if (realUrl.pathname === "/" || realUrl.pathname === "/index") {
res.end("主页");
} else {
res.end("其他页面");
}
});
server.listen(3000);

如何返回页面:fs

文件读取

当我们想要给前端返回一个页面的时候,我们需要先加载一下 html 文件,然后返回

这里在插一嘴:前端的所有路由都是假路由!

首先呢,在项目下新建一个 view 文件夹,里面存放着我么要返回给前端展示的页面html文件

然后写好html ,运行下面的 node 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const http = require("http");
const url = require("url");
const fs = require("fs");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8");
let reqUrl = req.url;
let realUrl = url.parse(reqUrl);
console.log(realUrl);
if (realUrl.pathname === "/" || realUrl.pathname === "/index") {
let htmlData = fs.readFileSync("./view/index.html");
res.end(htmlData);
} else {
let htmlData = fs.readFileSync("./view/other.html");
res.end(htmlData);
}
});
server.listen(3000);

当然,如果html文件比较大的话,一次性读到内存,对于比较次的电脑会比较吃力,我们可以通过流读取来优化一下。

流读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const http = require("http");
const url = require("url");
const fs = require("fs");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8");
let reqUrl = req.url;
let realUrl = url.parse(reqUrl);
if (realUrl.pathname === "/" || realUrl.pathname === "/index") {
// 流方式:节约内存
let rs = fs.createReadStream("./view/index.html");
// 通过管道写到 res 里
rs.pipe(res);
} else {
let rs = fs.createReadStream("./view/other.html");
rs.pipe(res);
}
});
server.listen(3000);

处理页面中引入的 JS:设置 Content-type

当我们在 index.html 页面上引入了一个脚本的时候

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="./a.js"></script>
</head>
<body>
<h2>我是主页</h2>
</body>
</html>

此时,这个 a.js 会有作用吗?

访问一下http://localhost:3000/ 后,发现报错了

Uncaught SyntaxError: Unexpected token ‘<’

这是我们引入的资源不正确导致的,至于为什么报这个错误,我也不懂~

我是知道 a.js 这个文件页面它没找到,那如何处理呢?我们也需要把这个 js 读出取来,然后放到res

为什么这么可以呢?浅显的理解就是:当页面发现你引入了 a.js 的时候,会发起一个请求,去后台请求 a.js ,这个是在 createServer 里能打印出来的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const http = require("http");
const url = require("url");
const fs = require("fs");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8");
let reqUrl = req.url;
let realUrl = url.parse(reqUrl);
console.log(reqUrl);
if (realUrl.pathname === "/" || realUrl.pathname === "/index") {
let rs = fs.createReadStream("./view/index.html");
rs.pipe(res);
} else if (realUrl.pathname === "/other") {
let rs = fs.createReadStream("./view/other.html");
rs.pipe(res);
} else {
// 处理 a.js
// 你会发现,在html 中引入的资源也会在 req.url 中找到
let rs = fs.createReadStream("./view" + realUrl.pathname);
rs.pipe(res);
}
});
server.listen(3000);

此时 a.js 就可以正常的引入了,不过会报错,因为找不到 favicon.ico,这个先不用管,或者添加个if条件,也并不是重点,只需要了解知道即可。

我们请求的所有资源都会走 createServer 的,比方说页面中引入了a.js,那么他也会走一遍 createServer
比较隐形的例子就是 favicon.ico 了!所以你会疑惑,为什么上面的代码 req 打印了两遍,原因可能是这个哦。

其他资源处理 Content-type:MIME

此时还会有一个问题,所有的资源需要配置适合自己的 Content-type,否则就会出现错误或者失效,比方说我写一个 css ,并在页面中引入

1
2
3
4
// css 文件
body {
background: red;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// index.js
// 服务器启动脚本
const http = require("http");
const url = require("url");
const fs = require("fs");
// const mime = require("./mime.json") // 注意这里注释掉了~等会记得松开注释
const path = require("path");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8");
let urlObj = url.parse(req.url);
console.log(urlObj.pathname);
if (urlObj.pathname === "/" || urlObj.pathname === "/index") {
let indexData = fs.createReadStream("./views/index.html");
indexData.pipe(res);
} else {
if (urlObj.pathname !== "/favicon.ico") {
// let ext = path.extname(urlObj.pathname)
// res.setHeader("Content-Type", mime[ext]) // 通过请求的资源后缀名,来返回对应的 Content-type 的类型
let resData = fs.createReadStream("./views" + urlObj.pathname);
resData.pipe(res);
}
}
});
server.listen(3001);

整体展示如下,注意看一下右边的文件路径。
在这里插入图片描述

页面样式如下
在这里插入图片描述
而且页面的效果也没有,这个 css 根本没起作用啊,所以要配置一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const http = require("http");
const url = require("url");
const fs = require("fs");
const mime = require("./mime.json"); // 引入 MIME
const path = require("path");
const server = http.createServer((req, res) => {
res.setHeader("content-type", "text/html;charset=utf-8");
let urlObj = url.parse(req.url);
console.log(urlObj.pathname);
if (urlObj.pathname === "/" || urlObj.pathname === "/index") {
let indexData = fs.createReadStream("./views/index.html");
indexData.pipe(res);
} else {
if (urlObj.pathname !== "/favicon.ico") {
let ext = path.extname(urlObj.pathname);
res.setHeader("Content-Type", mime[ext]); // 通过请求的资源后缀名,来返回对应的 Content-type 的类型
let resData = fs.createReadStream("./views" + urlObj.pathname);
resData.pipe(res);
}
}
});
server.listen(3001);

配置后的页面
在这里插入图片描述

其中 MIME.json 的代码在文章的最下面。


模板引擎

我单独提取出来了,放在一篇文章里太挤了。


Koa 框架

官网戳我,它是 express 原班人马制作的,比 express 更加轻量。

创建一个服务:Hello Koa.js

可以和原生 node 做个对比

1
2
3
4
5
6
// Node 原生
const http = require("http");
const server = http.createServer((req, res) => {
res.end("hello Node.js");
});
server.listen(3000);
1
2
3
4
5
6
7
// Koa
const Koa = require("koa");
const app = new Koa();
app.use((ctx, next) => {
ctx.body = "你好";
});
app.listen(3000);

感觉好像也没简单多少啊,别急,看看它是如何处理路由还有其他的功能的。

中间件用法

koa 中引入了中间件这个东西,中间件会把回调函数里面写的功能,添加到 app 实例中去,比方说上面的 🌰

1
2
3
app.use((ctx, next) => {
ctx.body = "你好";
});

其中 ctxcontext 的缩写,意为上下文,可以让上下中间件产生关联。

原生 node 中的 res 被 koa 封装到了 ctx.res 里,req 也是同理的,这个知识点在 Koa官网中称之为 别名

比方说别人已经封装好了几个功能函数(中间件),我们引入后,拿来 app.use()即可。

app.use() 可以理解为注册

1
2
3
4
5
6
7
8
9
10
11
12
13
const Koa = require("koa");
const app = new Koa();
let middleware1 = async function (ctx, next) {
console.log("假设我是一个封装好的中间件1");
await next();
};
let middleware2 = async function (ctx, next) {
console.log("假设我是一个封装好的中间件2");
await next();
};
app.use(middleware1);
app.use(middleware2);
app.listen(3000);

其中 next 是转交的功能。会把函数放到异步队列

执行顺序:洋葱模型

遵循洋葱模型,可以理解成把 next() 替换成 下一个中间件的函数语句。
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Koa = require("koa");
const app = new Koa();
let middleware1 = async function (ctx, next) {
console.log("one start...");
ctx.body = "hello";
await new Promise((resolve) => {
setTimeout(() => {
console.log("异步操作");
resolve();
}, 1000);
});
await next();
console.log("one end...");
};
let middleware2 = async function (ctx, next) {
console.log("two start...");
ctx.body = "world";
console.log("two end...");
};
app.use(middleware1);
app.use(middleware2);
app.listen(3000);

上面的代码执行后输出如下
在这里插入图片描述
理解过程
在这里插入图片描述

错误处理:监听 error

如果那个中间件出现了错误,可以通过监听 error 事件,来打印 & 处理异常。

1
2
3
app.on("error", (err) => {
console.log(err);
});

在这里插入图片描述

路由

路由需要我们引入路由组件 require("koa-router")

1
2
3
4
5
6
7
8
9
10
const Koa = require("koa");
const Router = require("koa-router");
let app = new Koa();
let router = new Router();
router.get("/", async (ctx, next) => {
// 加载页面
await ctx.render("index.pug");
});
app.use(router.routes());
app.listen(3000);

router.get 就相当于 用 get 方式请求后台,其他请求方式类似。

使用模板引擎加载页面:koa-views

有了中间件,可以省了不少的事情,可以跟原生的做个对比~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Koa = require("koa");
const Router = require("koa-router");
const views = require("koa-views");
let app = new Koa();
let router = new Router();
// 使用中间件,告诉我们的页面文件的路径在哪儿
// 其中第二个参数:配置模板引擎的格式
app.use(views(__dirname + "/views"), {
extension: "pug",
});
router.get("/", async (ctx, next) => {
// 加载页面
await ctx.render("index.pug");
});
app.use(router.routes());
app.listen(3000);

在这里插入图片描述

引入静态外部资源:koa-static

这个组件叫做:静态 web 托管服务中间件

这也是一个外部的中间件,需要 npm install koa-static,你会发现比原生的 fs 模块要简单很多。

基本的思路就是:

  • 通过请求路径获取正确的文件地址
  • 通过地址获取对应的文件
  • 使用Node.jsAPI返回对应的文件,并设置相应的header

实例:我们先在 index.pug 中引入一个脚本

1
2
3
4
5
6
7
8
9
10
11
doctype html
html(lang='en')
head
meta(charset='UTF-8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
meta(http-equiv='X-UA-Compatible', content='ie=edge')
script(src="a.js")
title Document
body
h1
| 测试标题pug

然后执行 一下脚本,启动服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const Koa = require("koa");
const Router = require("koa-router");
const views = require("koa-views");
const static = require("koa-static");
let app = new Koa();
let router = new Router();
app.use(views(__dirname + "/views"), {
extension: "pug",
});
app.use(static(__dirname + "/static")); // 添加查找静态资源的中间件,配置路径
router.get("/", async (ctx, next) => {
await ctx.render("index.pug");
});
app.use(router.routes());
app.listen(3000);

发现可以正常加载脚本!!ok

在这里插入图片描述

注意!!!
页面中引入的脚本尽量不去加前缀
在这里插入图片描述

在 Node 原生的讲解可以知道,引入外部资源也是一种请求,浏览器会发起一个请求到后台,我们后台需要找到文件并返回给浏览器~

我们用推荐的写法之所以能找到,是因为后端找到了这个资源

在这里插入图片描述
如果你用./static/a.js 这样引入的话,你以为页面能够正确引入,实则非也。
在这里插入图片描述
原因是因为,如果你是这样声明的话,Node 就会去访问 /static 下的文件,并把它替代成 localhost:3000

下图中是为了验证我的猜想。
在这里插入图片描述

所以只需要记住,**static() 声明的路径就是页面中要找的资源的最顶层**。koa-static 帮我们处理了托管静态文件的路径

1
2
3
// 这里声明成这样子,后端会在遇到请求静态资源的时候,到 dirname + '/static' 这个路径下去寻找
// 前端请求的样子是:localhost:3000/a.js
app.use(static(__dirname + "/static"));

在这里插入图片描述

接收 post 请求传递来的参数:koa-body

如需想要获取 post 请求来的参数的话,需要添加这个中间件

不然拿不到 post 发过来的参数,打印出来的也是 undefined在这里插入图片描述
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
const { koaBody } = require("koa-body");

// // [npm koaBody的说明] (https://www.npmjs.com/package/koa-body)
// 2022-11-30 下面这行的这个引用已经不好使了,根据官方的引用是这样的
// const Body = require('koa-body')
app.use(
Body({
multipart: true,
})
);

// 取值
console.log(ctx.request.body);

取值可以通过 ctx.request.body来拿到值。


其他知识补充

默认请求方式为 get 的几种情况

有些请求默认是 get 的,比方说地址栏、脚本 scripsrc=""img 图片的 srchref=""

环境变量:__dirname

这个 __dirnameNode 中的系统变量,它的值是当前所在文件的上一级文件夹的路径。
在这里插入图片描述

代码

MIME.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
{ ".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"
}