手动实现 koa2 的 static 服务和 koa-static 中间件的使用
一、需求
为 koa2 实现静态资源加载的服务,用于访问 css/js/img 等文件,访问图片的话,返回二进制文件,其他文件则直接输出字符串。
我下面自己的实现,过于简单或者没有考虑更多层面的东西,推荐 https://chenshenhai.github.io/koa2-note/note/static/server.html这篇文章。
二、实现路由和工具方法
项目目录:
1、路由说明:
通过 /static/*
进行通用的 /static/img/1.png
类似路由匹配工作。
staticMiddleware
是核心的实现中间件(见第三点,实现中间件)。
const Router = require('koa-router');
const staticMiddleware = require('../middlewares/staticMiddleware');
const router = new Router();
router.use(staticMiddleware());
router.get('/',async (ctx,next)=>{
ctx.body = `<h1>Index</h1>`;
});
router.get('static/*', async (ctx,next)=>{});
module.exports = router;
2、工具方法:extname
获取扩展名
位置:
utils/extname.js
通过传入 ctx.url
进行分割,得到最后的扩展名
function extname(url) {
let ext = url.split('.');
ext = ext[ext.length - 1];
return ext.toLowerCase();
}
module.exports = extname;
3、工具方法:getFilePath
获取文件的本地路径
位置:
utils/getFilePath.js
没有做配置,直接写死的,其实本地是没有 static
这个目录,而是放在 ./public
目录中。
因此需要将 /static/
去掉,拼上 public/
function getFilePath(url){
const staticStr = '/static/';
const public = 'public/';
const filePath = url.substr(staticStr.length);
return `${public}${filePath}`;
}
module.exports = getFilePath;
4、工具方法:getFileContent
读取文件内容
位置:
utils/getFileContent.js
使用 fs.readFile()
进行异步文件读取,读取成功则 resolve
,失败则 reject
。
使用的 url 是通过 getFilePath()
返回的。
const fs = require('fs');
const path = require('path');
function getFile(url){
return new Promise((resolve,reject)=>{
fs.readFile(path.resolve(url),(err,data)=>{
if(err) reject(err);
resolve(data);
});
})
}
module.exports = getFile;
5、工具方法:mimetypes
返回文件类型
位置:
utils/mimetypes.js
通过 extname
后缀获取文件的 mimetype
,这个就直接照着 这篇文章 的内容写的一样。
const mimetypes = {
'css': 'text/css',
'less': 'text/css',
'gif': 'image/gif',
'html': 'text/html',
'ico': 'image/x-icon',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'json': 'application/json',
'pdf': 'application/pdf',
'png': 'image/png',
'svg': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
'tiff': 'image/tiff',
'txt': 'text/plain',
'wav': 'audio/x-wav',
'wma': 'audio/x-ms-wma',
'wmv': 'video/x-ms-wmv',
'xml': 'text/xml'
}
module.exports = mimetypes;
三、实现中间件
引入需要的工具方法,其中 getStatic
是 async
方法,主要是因为 getFileContent()
通过异步文件读取,所以需要进行 await
。
getStatic()
方法主要是返回文件的内容、类型。
中间件在处理的时候,如果能够获取到文件,并且请求的文件是图片类型,则直接通过原生的 node.js
的 ctx.res.write(obj.file, 'binary');
进行二进制输出。其他的则输出字符串内容(readFile 读取的是 <Buffer>
)。
文件位置:
./middlewares/staticMiddleware
const extname = require('../utils/extame');
const mimetypes = require('../utils/mimetypes');
const getFileContent = require('../utils/getFileContent');
const getFilePath = require('../utils/getFilePath');
async function getStatic(ctx) {
try{
const ext = extname(ctx.url);
const mimetype = mimetypes[ext];
const filePath = getFilePath(ctx.url);
let file = await getFileContent(filePath);
return {code:0,file,mimetype};
}catch(err){
return {code:-1,err}
}
}
module.exports = () => {
return async (ctx, next) => {
let obj = await getStatic(ctx);
if(obj.code === -1) return ctx.res.writeHead(404);
if(obj.mimetype) ctx.type = obj.mimetype;
if(obj.mimetype && obj.mimetype.startsWith('image/')) {
ctx.res.writeHead(200);
ctx.res.write(obj.file, 'binary');
ctx.res.end();
}else{
ctx.body = obj.file.toString();
}
await next();
}
}
四、使用 koa-static
中间件
1、安装
yarn add koa-static
2、引入并使用
const Koa = require('koa');
const koaStatic = require('koa-static');
const app = new Koa();
// 相对于 app.js 的路径
const staticPath = './public';
// 使用中间件
app.use(koaStatic(path.join( __dirname, staticPath)));
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://www.ptbird.cn/koa2-static-by-self.html
转载请注明文章原始出处 !