【學習Koa】原生koa2 靜態資源服務器例子


實現思路

  • 首先讀取當前路徑下所有的文件和文件夾
  • 當去點擊某個列表項時判斷其實文件還是文件夾,文件的話直接讀取,文件夾則再次利用上一個步驟讀取並展示

文件結構

文件結構

代碼

index.js 入口文件

const Koa = require('koa')
const path = require('path')
const getContent = require('./util/content')
const mimes = require('./util/mimes')

const app = new Koa()

const staticPath = './static'

function parseMime(url) {
  let extName = path.extname(url)
  extName = extName ? extName.slice(1) : 'unknown'
  return mimes[extName]
}

app.use(async (ctx) => {

  if (ctx.path === '/favicon.ico') return;

  let absoluteStaicPath = path.join(__dirname, staticPath)
  let content = await getContent(ctx, absoluteStaicPath)
  let mime = parseMime(ctx.url)

  if (mime) {
    ctx.type = mime
  }

  if (mime && (mime.includes('image/') || mime.includes('video/'))) {
    ctx.res.writeHead(200)
    ctx.res.write(content, 'binary')
    ctx.res.end()
  } else {
    ctx.body = content
  }

})

app.listen(3000, function (params) {
  console.log('running at 127.0.0.1:3000')
})

content.js 獲取內容

const fs = require('fs')
const path = require('path')
const dir = require('./dir')
const file = require('./file')

function getContent(ctx, absoluteStaticPath) {
  
  let reqPath = path.join(absoluteStaticPath, ctx.url)
  const exist = fs.existsSync(reqPath)
  let content = ''

  if (!exist) {
    content = '404 not found'
  } else {
    let status = fs.statSync(reqPath)

    if (status.isDirectory()) {
      content = dir(ctx.path, reqPath)
    } else {
      content = file(reqPath)
    }
  }

  return content
}

module.exports = getContent

file.js 讀取文件

const fs = require('fs')

function file(reqPath) {
  return fs.readFileSync(reqPath, 'binary')
}

module.exports = file

dir.js 讀取文件夾

const walk = require('./walk')

function dir(path, reqPath) {

  let {
    dirList,
    fileList
  } = walk(reqPath)

  let html = ''
  function category(path, type, list) {
    html += `<h2>${type}: </h2>`
    html += '<ul>'
    for (const item of list) {
      html += `<li><a href="${path === '/' ? '' : path}/${item}">${item}</a></li>`
    }
    html += '</ul>'
  }
  
  dirList.length && category(path, '文件夾', dirList)
  fileList.length && category(path, '文件', fileList)

  return html
}

module.exports = dir

walk.js 遍歷目錄,歸類文件和文件夾

const fs = require('fs')
const mimes = require('./mimes')

function walk(reqPath) {

  const dirList = [], fileList = []
  const files =  fs.readdirSync(reqPath)

  for (const file of files) {
    // 判斷文件是文件夾還是文件
    let file_split = file.split('.')
    // 根據mime類型判斷, 因為文件夾的名字也中也是可以帶有.的
    let mimeType = file_split.length > 1 ? file_split[file_split.length-1] : ''

    if (mimes[mimeType] === void 0) {
      dirList.push(file)
    } else {
      fileList.push(file)
    }
  }
  
  return { dirList, fileList }
}

module.exports = walk

mimes.js

const mimes = {
  'css': 'text/css',
  'less': 'text/css',
  'txt': 'text/plain',
  'html': 'text/html',
  'xml': 'text/xml',
  'js': 'text/javascript',
  'json': 'application/json',
  'pdf': 'application/pdf',
  'wav': 'audio/x-wav',
  'wmv': 'video/x-mx-wmv',
  'gif': 'image/gif',
  'jpeg': 'image/jpeg',
  'jpg': 'image/jpeg',
  'png': 'image/png',
  'svg': 'image/svg+xml',
  'tiff': 'image/tiff',
  'icon': 'image/x-icon',
  'mp4': 'video/mp4'
}

module.exports = mimes

結果


來源

原生koa2 靜態資源服務器例子


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM