基于node.js的静态资源服务器
最近碰见了一个面试题 手撸一个基于node的静态资源服务器。以下是我个人的思路
直接先贴代码
const http = require('http')
const fs = require('fs')
const path = require('path')
const server = http.createServer()
server.on('request', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*') // 设置跨域
controllers(req, res)
// readStatic(url, res)
})
// 4.启动服务器
server.listen(8080, () => {
console.log('start is server')
})
let redis = {}
setInterval(() => { // 用定时器有点草率但是没时间了 先这样凑合做个简单的清楚
redis = {} // 时间够的话 指定不会这样清,会对每个key进行一个时间绑定。如果时间到期则回清除 类似于session
}, 3000)
const controllers = async (req, res) => {
const url = req.url
if (url === '/favicon.ico') return
if (url === '/') {
const files = await getFilesName()
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' })
let str = ''
for (var i = 0; i < files.length; i++) {
str = str + `<a href=${files[i]}>${files[i]}</a><br>`
}
const query = 'https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js'
res.end(`<body><div id='router'></div></body><script src="${query}"></script><script> document.getElementById('router').innerHTML ='${str}'</script> `)
res.end(`<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
let domA = document.getElementsByTagName("a")
for(var i=0;i<domA.length;i++){
let url = http://localhost:8080/+ domA[i].innerHTML
domA[i].onclick = function(){
$.ajax({url:url,type:'GET',success:function(data){
console.log(data)
}})
}
}
</script>`)
} else {
readStatic(url, res)
}
}
const readStatic = function (url, res) {
fs.readFile(path.join(__dirname, 'static', url), (_err, data) => { // 路径拼接去static目录下找对应的文件
const urlItem = url.split('.')
const Contenttype = mime[urlItem[1]] || 'application/octet-stream'
if (urlItem[1] === undefined) {
if (!redis[url]) {
res.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Disposition': `attachment; filename=${urlItem[0]}`
})
fs.createReadStream(`${__dirname}/static${url}`).pipe(res)
redis[url] = true
} else {
res.writeHead(403, { 'Content-type': Contenttype })
res.end()
}
} else {
res.writeHead(200, { 'Content-Type': Contenttype + ';charset=utf-8' })
res.end(data)
}
})
}
const getFilesName = () => {
return new Promise((resolve, reject) => {
fs.readdir(`${__dirname}/static`, function (_err, data) {
if (_err) {
return reject(_err)
}
const item = []
for (const value of data) {
item.push(value)
}
resolve(item)
})
})
}
// const isBuffer = function (str) {
// return str && typeof str === 'object' && Buffer.isBuffer(str)
// }
const mime = {
css: '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'
}
- 首先需要建立一个app.js文件,该文件主要用于搭建服务器,所谓的静态资源服务器就是把服务器上的文件通过http进行发送或者说是做处理
- 比如通过请求某个地址需要把某个文件夹下面的html渲染在浏览器上,或者说下载某个文件,也或者说把某个文件夹下面的txt文件的内容显示在浏览器上。html的渲染不是显示源码而是显示的是网页
- 主文件app.js建立好后就需要 建一个静态文件夹用于放我们需要显示或者下载的文件
-
我的目录,我在static下面放了四个类型不一样的文件,我的目的是通过请求/index.js路径就显示源码在网页,请求/index.html就把html渲染在网页,/index就是直接下载该文件
-
首先需要搭个基本的服务器 这个时候就会用到http模块 ,服务器搭建完成后
-
我的做法是通过后缀名去区分不同的文件,通过区分不同的文件给他设置对应的content-type类型
- -
一些类型都封装在mine对象中
-
还有一个需求则是把根目录下的文件当做a标签一样点击后进行不同的操作,其实就是点击后发送ajax请求,当用户请求
127.0.0.1:8080/
路径的时候我会返他一个我自己的html页面这个页面是会显示static目录下的文件如图 -
其实就是MVC的模板渲染我这个是最基础的,如果你把Html当做字符串返回在浏览器上和本地加载html是一样的但是
content-type
得设成text/html
否则浏览器是不会知道你给他了一个什么东西,这里偷了个懒 引入了百度的jquery写了个ajax请求。没有直接写原生的XMLHttpRequest
总结:其实就是构建一个Http服务然后在本地建立一个static的静态资源库,然后通过fs文件操作来进行数据返回,根据不同的需求返回不同的结果。难点在于对http的content-type的理解,写的时候因为不熟悉踩了不少坑。这个代码还可以继续的优化。考察的就是代码能力,可惜,平时库用太多忘了http.js的操作和content-type的设置,其实如果扩展起来就类似于nginx的功能。 还是太菜没抓住机会!
码云地址:https://gitee.com/gong-yongchao/static-server
本文地址:https://blog.csdn.net/a519637560/article/details/109645217
上一篇: cdr怎么设计眩晕底纹? cdr复古背景图的设计方法
下一篇: 龙骨为什么比排骨便宜?怎么挑选龙骨?