}
else if (stats.isDirectory()) {
const files = await readdir(filePath)
response.statusCode = 200
response.setHeader('content-type', 'text/plain')
response.end(files.join(','))
}
} catch (err) {
console.error(err)
response.statusCode = 404
response.setHeader('content-type', 'text/plain')
response.end(`${filePath} is not a file`)
}
}
因为
fs.stat() 和
fs.readdir() 都可能返回 error,所以使用 try-catch 捕获。使用异步时需注意,异步回调需要使用 await 返回异步操作,不加 await 返回的是一个 promise,而且 await 必须在async里面使用。
四、添加模版引擎
从上面的例子是手工输入文件路径,然后返回资源文件。现在优化这个例子,将文件目录变成 html 的 a 链接,点击后返回文件资源。
在第一个例子中使用
response.write() 插入 HTML 标签,这种方式显然是不友好的。这时候就使用模版引擎做到拼接 HTML。常用的模版引擎有很多,ejs、jade、handlebars,这里的使用ejs:
npm i ejs新建一个模版 src/template/index.ejs ,和 html 文件很像:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Node Server</title>
</head>
<body>
<% files.forEach(function(name){ %>
<a href="../<%= dir %>/<%= name %>" rel="external nofollow" > <%= name %></a><br>
<% }) %>
</body>
</html>再次修改 route.js,添加 ejs 模版并
ejs.render() ,在文件目录的代码中传递 files、dir 等参数:
// server/route.jsconst fs = require('fs')
const util = require('util')
const path = require('path')
const ejs = require('ejs')
const config = require('./config')
// 异步优化
const stat = util.promisify(fs.stat)
const readdir = util.promisify(fs.readdir)
// 引入模版
const tplPath = path.join(__dirname,'../src/template/index.ejs')
const sourse = fs.readFileSync(tplPath) // 读出来的是buffer
module.exports = async function (request, response, filePath) {
try {
const stats = await stat(filePath)
if (stats.isFile()) {
response.statusCode = 200
···
}
else if (stats.isDirectory()) {
const files = await readdir(filePath)
response.statusCode = 200
response.setHeader('content-type', 'text/html')
// response.end(files.join(','))
const dir = path.relative(config.root, filePath) // 相对于根目录









