前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Node.js做静态资源服务器

Node.js做静态资源服务器

作者头像
切图仔
发布2022-09-14 15:11:40
2.3K0
发布2022-09-14 15:11:40
举报
文章被收录于专栏:生如夏花绚烂

在上一篇文章介绍了Node.js基础API 接下来我们做一个案例,用Node.js实现静态资源服务器

目录结构

首先新键如下目录结构

config:存放一些配置文件

helper:辅助文件

template:模板文件(后面会使用到模板引擎)

app.js:入口文件

搭建服务

我们要根据客户端请求的url返回相应的文件/目录信息,所以我们要先搭建服务

使用http模块搭建

代码语言:javascript
复制
const http = require('http');
const conf = require('./config/defaultConf')
const server = http.createServer((req,res)=>{
    res.statusCode = 200
    res.setHeader('Content-Type','text/plain')
    res.end('hello word')

})

server.listen(conf.port,conf.hostname,()=>{
    console.info('server start')
})

配置文件

代码语言:javascript
复制
module.exports = {
    root:process.cwd(),
    hostname :'127.0.0.1',
    port:'3000'
}

要做一个资源服务器首先我们得获取到用户请求的url,得到url后将当前node执行的目录与url进行拼接

代码语言:javascript
复制
const path = require('path')
...
const server = http.createServer((req,res)=>{
    res.statusCode = 200
    res.setHeader('Content-Type','text/plain')
    const filePath = path.join(conf.root,req.url)

})
...

得到url后有三种情况

1.url指向某个文件

2.url指向某个目录

3.不存在的路径

当url指向某个文件时我们直接返回,当指向某个目录时,我们将该目录的文件全部列出,并且实现超链接,当没有该目录或文件时返回提示信息“没有该文件”

接下来通过代码实现 我们将这部分逻辑写进helper/route.js

代码语言:javascript
复制
const fs = require('fs')
const path = require('path')
const {promisify} = require('util')
const stat = promisify(fs.stat)
const readdir = promisify(fs.readdir)
const conf = require('../config/defaultConf');
const mime = require('../helper/mime')
module.exports = async function(req,res,filepath){
    try{
        const stats = await stat(filepath)//异步
        if(stats.isFile()){
            //文件
            //根据文件类型返回相应mime
            const contentType = mime(filepath)
            res.statusCode = 200
            res.setHeader('Content-type',contentType)
            fs.createReadStream(filepath).pipe(res)//读取文件流并返回
        }else if(stats.isDirectory()){
            //目录
            //1.读取该目录所有内容
            const files = await readdir(filepath)
            res.statusCode = 200
            res.setHeader('Content-Type','text/html')
            res.end(files.join(','))

        }
    }catch(e){
        console.log(e)

    }
}

在route.js中我们引入promisify模块引入,将相关文件操作封装成promise对象,这样可以使我们在读取文件时不用进行各种回调,通过async与await时同步的方式去做异步的事情。 我们还引入了自定义模块mime这个模块放置了文件类型对应的contentType,以确保我们发送给客户端正确的contentType helper/mime.js

代码语言:javascript
复制
const path = require('path')
const mimeTypes = {
    'css':'text/css',
    'gif':'image/gif',
    'html':'text/html',
    'ico':'image/x-ico',
    'jpeg':'image/jpeg',
    'jpg':'image/jpeg',
    'js':'text/javascript',
    'json':'application/json',
    'pdf':'application/pdf',
    'png':'image/png',
    'svg':'image/svg+xml',
    'txt':'text/plain',
}

module.exports = (filePath)=>{
    let ext = path.extname(filePath)
    .split('.')
    .pop()
    .toLocaleLowerCase();
    if(!ext){
        ext = filePath;
    }
    return mimeTypes[ext] || mimeTypes['txt']
}

到此我们已经可以根据url返回文件,目录了

但是不够美观关,且没有超链接,如点击目录跳转该目录的内容

针对这个问题我们可以通过模板引擎实现 1.引入模板引擎 这里我们使用handlebars

代码语言:javascript
复制
cnpm i handlebars

2.在route.js引入

代码语言:javascript
复制
const fs = require('fs')
const path = require('path')
const {promisify} = require('util')
const stat = promisify(fs.stat)
const readdir = promisify(fs.readdir)
const conf = require('../config/defaultConf');
const mime = require('../helper/mime')
const Handlebars = require('handlebars')//引入模板引擎
const tplPath = path.join(__dirname,'../template/dir.tpl')
const source = fs.readFileSync(tplPath,'utf-8')//引入模板文件
const template = Handlebars.compile(source)

module.exports = async function(req,res,filepath){
    try{
        const stats = await stat(filepath)//异步
        if(stats.isFile()){
            //文件
            //根据文件类型返回相应mime
            const contentType = mime(filepath)
            res.statusCode = 200
            res.setHeader('Content-type',contentType)
            fs.createReadStream(filepath).pipe(res)//读取文件流并返回
        }else if(stats.isDirectory()){
            //目录
            //1.读取该目录所有内容
            const files = await readdir(filepath)//
            res.statusCode = 200
            res.setHeader('Content-Type','text/html')
            const dir = path.relative(conf.root,filepath)//该目录的相对路径
            const data = {
                // files,
                // title:path.basename(filePath),
                // dir:dir?`/${dir}`:''
                files:files.map(file=>{
                    return {
                        file,
                        icon:mime(file)
                    }
                }),
                title:path.basename(filepath),
                dir:dir?`/${dir}`:''

            }
            res.end(template(data))

        }
    }catch(e){
        console.log(e)

    }
}

浏览器访问如下

此外我们还可以对静态资源进行压缩,提高访问速度 在配置文件设置可以被压缩的文件

代码语言:javascript
复制
module.exports = {
    root:process.cwd(),
    hostname :'127.0.0.1',
    port:'3000',
    compress:/\.(html|js|css|md)/
}

新键helper/compress.js

代码语言:javascript
复制
const {createGzip,createDeflate} = require('zlib')
module.exports = (rs,req,res)=>{
    const acceptEncoding = req.headers['accept-encoding'];
        //浏览器不支持压缩时直接返回
    if(!acceptEncoding||!acceptEncoding.match(/\b(gzip|deflate)\b/)){
        return rs;
    }else if(acceptEncoding.match(/\bgzip\b/)){
        res.setHeader('Content-Encoding','gzip')
        return rs.pipe(createGzip())
    }else if(acceptEncoding.match(/\bdeflate\b/)){
        res.setHeader('Content-Encoding','deflate')
        return rs.pipe(createDeflate())
    }
     
}

修改route.js

代码语言:javascript
复制
const compress = require('../helper/compress')
...
 const contentType = mime(filePath)
            res.statusCode = 200
            res.setHeader('Content-type',contentType)
            let rs = fs.createReadStream(filePath)
            //压缩文件
            if(filePath.match(conf.compress)){
                rs =compress(rs,req,res)
            }
            rs.pipe(res)
...
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-07-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录结构
  • 搭建服务
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档