Node.js 写一个简单的静态服务器 2

本文介绍如何使用Node.js创建服务器,根据用户请求处理文件和目录。通过读取URL,判断请求资源类型,返回文件内容或目录列表。利用fs模块实现文件读取与流式传输,提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下来,我们来写,根据用户请求来的 URL 进行判断:如果要访问的是文件夹,就返回文件夹下的列表;如果是文件,就返回文件的内容。

我们知道,用户请求的东西都封装到 req 中。

然后呢,我们可以在vs code 中debug 看看req 里面包含了哪些内容,如下。

那我们怎么拿到请求的url 呢,可以看到,req 里面有一个url 属性,我们获取它就可以了。

我们的需求就是,把用户当前执行的目录当作根目录。那我们可以使用process.cwd() 取得这个目录。我们可以在 src/config/defaultConfig.js 中配置如下。

module.exports = {
  root: process.cwd(),
  hostname: '127.0.0.1',
  port: 9527
}

然后App.js 中代码如下,即可获取url 中地址对应的服务器地址

const path = require('path');
const http = require('http');
const conf = require('./config/defaultConfig');

const server = http.createServer((req,res) => {
  const url = req.url;
  const filePath = path.join(conf.root, url);

  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/html');
  res.end(filePath);
});

server.listen(conf.port, conf.hostname, () => {
  const addr = `http://${conf.hostname}:${conf.port}`;
  console.log(`Server started at ${addr}`);
})

然后,我们使用fs 判断这个地址是文件夹还是文件。如下。如果没有这个文件,就返回 404,如果是一个文件,就返回文件的内容。如何返回文件的内容呢,我们使用了fs.creatReadStream 用流式方式将文件一点点读取到res 中。

const path = require('path');
const http = require('http');
const fs = require('fs');
const conf = require('./config/defaultConfig');

const server = http.createServer((req,res) => {
  const url = req.url;
  const filePath = path.join(conf.root, url);
  fs.stat(filePath, (err,stats) => {
    if (err) {
      res.statusCode = 404;
      res.setHeader('Content-Type', 'text/plain');
      res.end(`${filePath} is not a file or directory`);
      return;
    }
    if (stats.isFile()) {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/plain');
      fs.createReadStream(filePath).pipe(res)
    }
    if (stats.isDirectory()) {

    }
  })
  // res.statusCode = 200;
  // res.setHeader('Content-Type', 'text/html');
  res.end(filePath);
});

server.listen(conf.port, conf.hostname, () => {
  const addr = `http://${conf.hostname}:${conf.port}`;
  console.log(`Server started at ${addr}`);
})

如果不用流式的方式,那我们可以用下面的方式:这种写法,虽然也是异步,但是会很慢,它一次性把文件内容读到内存,然后再往res 里面放。推荐用流的方式传输。

    fs.readFile(filePath, (err, data) => {
        if (err) {
            // ...
            return;
        }
        res.end(data);
    })

如果地址是一个文件夹,那么我们将返回一个列表,对应这个文件夹下的列表。如下。

const path = require('path');
const http = require('http');
const fs = require('fs');
const conf = require('./config/defaultConfig');

const server = http.createServer((req,res) => {
  const url = req.url;
  const filePath = path.join(conf.root, url);
  fs.stat(filePath, (err,stats) => {
    if (err) {
      res.statusCode = 404;
      res.setHeader('Content-Type', 'text/plain');
      res.end(`${filePath} is not a file or directory`);
      return;
    }
    if (stats.isFile()) {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/plain');
      fs.createReadStream(filePath).pipe(res)
    }
    if (stats.isDirectory()) {
      fs.readdir(filePath, (err, files) => {
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/plain');
        res.end(files.join(", "));
      })
    }
  })
});

server.listen(conf.port, conf.hostname, () => {
  const addr = `http://${conf.hostname}:${conf.port}`;
  console.log(`Server started at ${addr}`);
})

Done.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值