不使用Express如何实现多文件服务?附问题代码及异常
嘿,我来帮你搞定这个问题!你的代码现在的问题很典型——因为fs.readFile是异步操作,你同时发起了两个文件读取请求,而且不管哪个先完成,都直接调用res.end(),这就导致响应被覆盖或者提前结束了,所以有时候页面只显示CSS内容。
问题根源
你的代码里同时执行了两个fs.readFile,这两个操作是并行的。当其中一个先完成时,就会调用res.writeHead和res.end,直接把响应发回给浏览器了。另一个操作完成后再调用res.end的时候,响应已经结束了,浏览器只会收到第一个返回的内容,所以才会出现有时候显示HTML、有时候显示CSS的情况。而且res.end()只能被调用一次,多次调用会导致错误。
正确的实现思路
要处理不同的请求路径,根据浏览器请求的URL来返回对应的文件,而不是不管请求什么都同时返回两个文件。具体步骤:
- 解析请求的URL,判断用户要访问的是哪个文件
- 根据不同的路径,设置对应的Content-Type
- 读取对应文件并返回,处理文件不存在的情况
完整代码示例
const http = require('http'); const fs = require('fs'); const path = require('path'); const port = 3000; http.createServer((req, res) => { // 处理请求路径,默认返回index.html let filePath = '.' + req.url; if (filePath === './') { filePath = './public/index.html'; } // 根据文件扩展名设置Content-Type const extname = path.extname(filePath); let contentType = 'text/html'; switch (extname) { case '.css': contentType = 'text/css'; break; case '.js': contentType = 'text/javascript'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpeg'; break; } // 读取文件并返回响应 fs.readFile(filePath, (err, content) => { if (err) { if (err.code === 'ENOENT') { // 文件不存在时返回404页面 fs.readFile('./public/404.html', (err, content) => { res.writeHead(404, {'Content-Type': 'text/html'}); res.end(content, 'utf-8'); }); } else { // 服务器内部错误 res.writeHead(500); res.end(`服务器错误: ${err.code}`, 'utf-8'); } } else { // 文件存在时返回对应内容 res.writeHead(200, {'Content-Type': contentType}); res.end(content, 'utf-8'); } }); }).listen(port, () => { console.log(`服务器运行在 http://localhost:${port}/`); });
代码说明
- 路径解析:通过
req.url获取浏览器请求的路径,默认访问根路径时返回index.html - Content-Type设置:用
path.extname获取文件扩展名,根据不同类型设置正确的响应头,这样浏览器才能正确解析文件 - 错误处理:处理文件不存在(404)和服务器内部错误(500)的情况,避免服务器崩溃
- 单一响应:每个请求只读取对应文件,调用一次
res.end(),确保响应内容正确无误
这样修改后,浏览器请求/时返回HTML,请求/styles/style.css时返回CSS,就不会出现内容混乱的问题了。
内容的提问来源于stack exchange,提问作者Marviuz
相关产品推荐
相关产品推荐

