P10:node實現靜態服務器 ~ 靜態讀取文件或文件夾

相關文章

如今咱們已經大體瞭解了node 的基本工做原理,如今來實現一個系統的功能 讀取文件或者文件夾node

採坑記錄

  • 中文輸出亂碼問題
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/plain')
    res.end('啊啊和嘎哈啊')
    複製代碼
    • 輸出中出現中文亂碼 附解決方案 ~
    res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
    複製代碼
    res.writeHead(200, { 'Context-Type': 'text/plain' })
    res.write('<head><meta charset="utf-8"/></head>')
    複製代碼
  • 文件讀取方式

    node 容許經過兩種方式讀取並輸出文件api

    • one : 以文件流的形式讀取與返回一塊兒進行,快 = 推薦
    fs.createReadStream(filePath).pipe(res)
    複製代碼
    • two : 先將文件整個讀取,而後將文件內容一塊兒返回,簡單說這就是api的蹩腳使用 =
    fs.readFile(filePath, (err, data) => {
        if (err) return
        res.end(data)
    })
    複製代碼

讀取文件或者文件夾

  • 廢話不說,上代碼

require('./config/defaultConfig') 更新爲如下bash

module.exports = {
      // 主機名稱
      hostname: '127.0.0.1',
      // 端口號
      port: 6969,
      // 當前文件夾
      root: process.cwd()
    }
複製代碼
// 引入http內置模塊
    const http = require('http')
    
    // 引入chalk 用於美化後臺打印
    const chalk = require('chalk')
    
    const path = require('path')
    const fs = require('fs')
    // 引入基本配置
    const conf = require('./config/defaultConfig')
    
    // 建立一個server 實例
    const server = http.createServer((rep, res) => {
      // 拿到路徑
      const filePath = path.join(conf.root, rep.url)
    
      // 判斷是否爲文件或者文件夾
      fs.stat(filePath, (err, stats) => {
        // 設置公共頭部信息
        res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
        if (err) {
          // 狀態碼
          res.statusCode = 404
    
          // 找不到提示文本
          res.end(`${filePath} is 404`)
    
          return
        }
        if (stats.isFile()) {
          // 若是是文件 返回文件內容
          res.statusCode = 200
    
          fs.createReadStream(filePath).pipe(res)
        } else if (stats.isDirectory()) {
          //  若是是文件夾,返回文件列表
          fs.readdir(filePath, (err, files) => {
            if (err) return
            res.statusCode = 200
    
            res.end(files.join(','))
          })
        }
      })
    })
    
    // 監聽 server 實例
    
    server.listen(conf.port, conf.hostname, () => {
      const addr = `http:// ${conf.hostname}:${conf.port}`
    
      console.info(`server startd at ${chalk.green(addr)}`)
    })

複製代碼

代碼優化

  • 上述代碼存在不少回調,代碼臃腫可讀性差。下面利用異步將回調去除,達到優化效果服務器

    • require-atomic-updates 注意eslint對於此項的限制, 爲此將實參await
      const fs = require('fs')
      
      const promisify = require('util').promisify
      const stat = promisify(fs.stat)
      const readdir = promisify(fs.readdir)
      
      module.exports = async function(rep, res, filePath) {
        // 規避此問題require-atomic-updates報告在異步函數中從新分配變量時可能發生的競爭條件錯誤
        const awaitRes = await res
        awaitRes.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
        try {
          const stats = await stat(filePath)
          if (stats.isFile()) {
            // 若是是文件 返回文件內容
            awaitRes.statusCode = 200
      
            fs.createReadStream(filePath).pipe(awaitRes)
          } else if (stats.isDirectory()) {
            //  若是是文件夾,返回文件列表
            const file = readdir(filePath)
            awaitRes.statusCode = 200
      
            awaitRes.end(file.join(','))
          }
        } catch (ex) {
          // 狀態碼
          awaitRes.statusCode = 404
      
          // 找不到提示文本
          awaitRes.end(`${filePath} is 404`)
        }
      }
      
      複製代碼
  • app.js文件變動爲app

    // 引入http內置模塊
    const http = require('http')
    
    // 引入chalk 用於美化後臺打印
    const chalk = require('chalk')
    
    const path = require('path')
    
    const route = require('./header/route')
    // 引入基本配置
    const conf = require('./config/defaultConfig')
    
    // 建立一個server 實例
    const server = http.createServer((rep, res) => {
      // 拿到路徑
      const filePath = path.join(conf.root, rep.url)
      route(rep, res, filePath)
    })
    
    // 監聽 server 實例
    
    server.listen(conf.port, conf.hostname, () => {
      const addr = `http:// ${conf.hostname}:${conf.port}`
    
      console.info(`server startd at ${chalk.green(addr)}`)
    })
    複製代碼
  • 至此實現了經過hash路徑輸入,實現文件或文件夾的讀取/前進後退異步

closeasync

相關文章
相關標籤/搜索