【前端37_Node 服务】Node 原生、Koa 框架

文章目录

    • 前言
    • Node 原生
      • 创建一个服务:Hello Node.js
      • 支持中文:设置 setHeader
      • 如何判断路由:req.url
      • 内置模块 url
      • 如何返回页面:fs
        • 文件读取
        • 流读取
      • 处理页面中引入的 JS:设置Content-type
      • 其他资源处理 Content-type:MIME
    • 模板引擎
    • Koa 框架
      • 创建一个服务:Hello Koa.js
      • 中间件
        • 用法
        • 执行顺序:洋葱模型
        • 错误处理:监听 error
        • 路由
        • 使用模板引擎加载页面:koa-views
        • 引入静态外部资源:koa-static
        • 接收 post 请求传递来的参数:koa-body
      • 其他知识补充
        • 默认请求方式为 get 的几种情况
        • 环境变量:__dirname
    • 代码
      • MIME.json

前言

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


Node 原生

创建一个服务:Hello Node.js

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

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

支持中文:设置 setHeader

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

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

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

// 页面
浣犲ソ Node.js

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

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=周杰伦 了。

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 他会帮你解析一下

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 脚本

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文件比较大的话,一次性读到内存,对于比较次的电脑会比较吃力,我们可以通过流读取来优化一下。

流读取

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 页面上引入了一个脚本的时候

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>Documenttitle>
    <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 里能打印出来的。

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 ,并在页面中引入

// css 文件
body{
    background: red;
}
// 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);

整体展示如下,注意看一下右边的文件路径。
【前端37_Node 服务】Node 原生、Koa 框架_第1张图片

页面样式如下
【前端37_Node 服务】Node 原生、Koa 框架_第2张图片
而且页面的效果也没有,这个css根本没起作用啊,所以要配置一下

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);

配置后的页面
【前端37_Node 服务】Node 原生、Koa 框架_第3张图片

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


模板引擎

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


Koa 框架

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

创建一个服务:Hello Koa.js

可以和原生 node 做个对比

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

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

中间件

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

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

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

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

用法

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

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() 替换成 下一个中间件的函数语句。
【前端37_Node 服务】Node 原生、Koa 框架_第4张图片

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);

上面的代码执行后输出如下
在这里插入图片描述
理解过程
【前端37_Node 服务】Node 原生、Koa 框架_第5张图片

错误处理:监听 error

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

app.on('error', err => {
    console.log(err);
})

【前端37_Node 服务】Node 原生、Koa 框架_第6张图片

路由

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

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

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

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);

【前端37_Node 服务】Node 原生、Koa 框架_第7张图片

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

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

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

基本的思路就是:

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

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

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

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

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

【前端37_Node 服务】Node 原生、Koa 框架_第8张图片

注意!!!
页面中引入的脚本尽量不去加前缀
【前端37_Node 服务】Node 原生、Koa 框架_第9张图片

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

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

【前端37_Node 服务】Node 原生、Koa 框架_第10张图片
如果你用./static/a.js 这样引入的话,你以为页面能够正确引入,实则非也。
【前端37_Node 服务】Node 原生、Koa 框架_第11张图片
原因是因为,如果你是这样声明的话,Node 就会去访问 /static 下的文件,并把它替代成 localhost:3000

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

也就是说,koa-static 是托管静态文件的地方吧【前端37_Node 服务】Node 原生、Koa 框架_第12张图片

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

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

不然拿不到 post 发过来的参数,打印出来的也是 undefined

【前端37_Node 服务】Node 原生、Koa 框架_第13张图片


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 中的系统变量,它的值是当前所在文件的上一级文件夹的路径。
【前端37_Node 服务】Node 原生、Koa 框架_第14张图片

代码

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"
}

你可能感兴趣的:(【前端】笔记,#,进阶,前端,javascript,macos)