1.1 创建基础的http服务
js
const http = require("http");
const url = require("url");
const config = {
port: 3000,
};
http
.createServer((req, res) => {
var pathname = url.parse(req.url).pathname;
console.log(pathname);
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("Hello World");
res.end();
})
.listen(config.port, () => {
console.log(`正在监听=======> ${config.port}端口`);
});
1.2 添加路由处理
js
const http = require("http");
const url = require("url");
const config = {
port: 3000,
};
const router = {
"/": (req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("Hello World");
res.end();
},
"/downloads": (req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("download");
res.end();
},
"/upload": (req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("upload");
res.end();
},
};
const route = (pathname, req, res) => {
if (router[pathname]) {
router[pathname](req, res);
} else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.write(`404 not found =========> ${pathname}`);
res.end();
}
};
http
.createServer((req, res) => {
var pathname = url.parse(req.url).pathname;
route(pathname, req, res);
console.log(pathname);
})
.listen(config.port, () => {
console.log(`正在监听=======> ${config.port}端口`);
});
1.3 读取文件夹,将文件夹中的信息返回
js
"/downloads": (req, res) => {
//文件列表页面
const dirPath = path.join(__dirname, "./uploads");
let result = "";
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
fileList = fs.readdirSync(dirPath);
let html = "";
fileList.forEach((fileName, index) => {
html += `<div><a target="_blank" href="/download?fileName=${fileName}" download="${fileName}">${
index + 1
}: ${fileName}</a></div>`;
});
res.end(html);
},
1.4 实现点击文件名称,下载文件
js
"/download": (req, res) => {
const { query } = url.parse(req.url);
const fileName = query.slice(9);
const filePath = path.join(__dirname, `./uploads/${fileName}`);
console.log(filePath);
const stat = fs.statSync(filePath);
if (!stat.isFile()) return res.end("文件不存在");
// 读取
const readStream = fs.createReadStream(filePath);
// const writeStream = fs.createWriteStream(fileName)
res.writeHead(200, {
"Content-Type": "application/octet-stream",
});
readStream.pipe(res);
},
1.5 文件上传页面
js
"/upload": (req, res) => {
const html = `<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<form action="/uploadFile" method="POST" enctype="multipart/form-data">
<span>选择文件</span>: <input type="file" name="file"/>
<br>
<input type="submit">
</form>
</html>
`
res.end(html);
},
1.6 文件上传方法
js
/*
由于使用的是`multipart/form-data`类型, 获取到的文件数据需要解析, 这里用到一个npm包 `busboy`
`npm init -y ` 初始化项目
`npm install -S busboy` 安装包
导入 `const Busboy = require('busboy')`
*/
"/uploadFile": (req, res) => {
const bb = Busboy({ headers: req.headers });
bb.on('file', (name, file, info) => {
// 名字 大小 格式
const { filename } = info;
// 根据时间创建名字 - 防止重名
const filePath = path.join(__dirname, `./uploads/${Date.now()}__${filename}`);
// 写入流
file.pipe(fs.createWriteStream(filePath));
});
bb.on('finish', function () {
res.writeHead(301, { Location: "/downloads" });
res.end();
})
req.pipe(bb)
},
1.7 最终代码
js
const http = require("http");
const url = require("url");
const fs = require("fs");
const path = require("path");
const Busboy = require("busboy");
const config = {
port: 3000,
};
const router = {
"/": (req, res) => {
const html = `
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<body>
<a href="/downloads">文件列表</a>
<br>
<a href="/upload">文件上传</a>
</body>
</html>
`;
res.end(html);
},
"/downloads": (req, res) => {
//文件列表页面
const dirPath = path.join(__dirname, "./uploads");
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
fileList = fs.readdirSync(dirPath);
let str = "";
fileList.forEach((fileName, index) => {
str += `<div>================> <a target="_blank" href="/download?fileName=${fileName}" download="${fileName}">
${fileName}</a></div>`;
});
const html = `
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
${str}
</html>
`;
res.end(html);
},
"/download": (req, res) => {
const { query } = url.parse(req.url);
if (!query) {
res.writeHead(301, { Location: "/" });
return res.end();
}
const fileName = query.slice(9);
const filePath = path.join(__dirname, `./uploads/${fileName}`);
console.log(filePath);
const stat = fs.statSync(filePath);
if (!stat.isFile()) return res.end("文件不存在");
// 读取
const readStream = fs.createReadStream(filePath);
// const writeStream = fs.createWriteStream(fileName)
res.writeHead(200, {
"Content-Type": "application/octet-stream",
});
readStream.pipe(res);
},
"/upload": (req, res) => {
const html = `<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<form action="/uploadFile" method="POST" enctype="multipart/form-data">
<span>选择文件</span>: <input type="file" name="file"/>
<br>
<input type="submit">
</form>
</html>
`;
res.end(html);
},
"/uploadFile": (req, res) => {
const bb = Busboy({ headers: req.headers });
bb.on("file", (name, file, info) => {
// 名字 大小 格式
const { filename } = info;
// 根据时间创建名字 - 防止重名
const filePath = path.join(
__dirname,
`./uploads/${Date.now()}__${filename}`
);
// 写入流
file.pipe(fs.createWriteStream(filePath));
});
bb.on("finish", function () {
res.writeHead(301, { Location: "/downloads" });
res.end();
});
req.pipe(bb);
},
};
const route = (pathname, req, res) => {
if (router[pathname]) {
router[pathname](req, res);
} else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.write(`404 not found =========> ${pathname}`);
res.end();
}
};
http
.createServer((req, res) => {
var pathname = url.parse(req.url).pathname;
route(pathname, req, res);
console.log(pathname);
})
.listen(config.port, () => {
console.log(`正在监听=======> ${config.port}端口`);
});