好的,前面我们写了一个简单到不可用的功能。现在,我们实现一下,返回的是一个友好的界面,如果返回值中有路径的话,那么它是可以点击并查看的。
那我们就需要模板引擎,这儿,我们使用 EJS
首先,我们安装 EJS https://github.com/mde/ejs , https://ejs.bootcss.com/
npm install ejs
安装好了后,我们就开始写代码了。
我们先来新建一个目录 src/templates。 我们把所有的模板文件都放这儿。在这个目录下新建文件main_page.ejs
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
a {
display: block;
}
</style>
</head>
<body>
<% files.map( file => { %>
<a href="<%= dir %>/<%= file %>" target="_blank" rel="external nofollow" > <%= file %> </a>
<% }) %>
</body>
</html>
我们进入src/helper 下的route.js ,先引用一下 ejs 。除了require 里,代码里我们一般还是使用绝对路径。下面我们先获取模板并解析。虽然是用同步的文件读取方法,但只会执行一次(以后可以从缓存中获取)并且后面函数依赖这个文件。因此用的是同步的方法。
const fs = require('fs');
const path = require('path');
const ejs = require('ejs');
const promisify = require('util').promisify;
const conf = require('../config/defaultConfig');
const stat = promisify(fs.stat);
const readdir = promisify(fs.readdir);
const ejsPath = path.join(__dirname, '../templates/main-page.ejs');
const source = fs.readFileSync(ejsPath,'utf-8');
module.exports = async function (req, res, filePath) {
try {
const stats = await stat(filePath);
if (stats.isFile()) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
fs.createReadStream(filePath).pipe(res)
}
if (stats.isDirectory()) {
const files = await readdir(filePath);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
const data = {
title: path.basename(filePath),
dir: path.relative(conf.root, filePath),
files
};
res.end(ejs.render(source, data));
}
} catch(ex) {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end(`${filePath} is not a file or directory`);
}
}
上面的代码,表面上是好的,但是在点入多层目录后,会有问题。是路径的问题。我们改成下面这样就好。
const fs = require('fs');
const path = require('path');
const ejs = require('ejs');
const promisify = require('util').promisify;
const conf = require('../config/defaultConfig');
const stat = promisify(fs.stat);
const readdir = promisify(fs.readdir);
const ejsPath = path.join(__dirname, '../templates/main-page.ejs');
const source = fs.readFileSync(ejsPath,'utf-8');
module.exports = async function (req, res, filePath) {
try {
const stats = await stat(filePath);
if (stats.isFile()) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
fs.createReadStream(filePath).pipe(res)
}
if (stats.isDirectory()) {
const files = await readdir(filePath);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
const dir = path.relative(conf.root, filePath)
const data = {
title: path.basename(filePath),
dir: dir ? `/${dir}` : '',
files
};
res.end(ejs.render(source, data));
}
} catch(ex) {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end(`${filePath} is not a file or directory`);
}
}
Done.