1. 演示效果
实现一个服务端的静态资源管理器,可以对服务端的文件进行上传、下载、删除等操作,并且对中文的文件名做了处理。效果如下:
2. 创建项目
本项目是使用 express
模板生成器创建的,需要先安装 express-generator
模板生成器,在终端运行:
$ cnpm i -g express-generator
然后在需要创建项目的文件夹路径处,打开终端依次执行下列命令:
# 创建项目
$ express -e myapp
# 进入项目的目录
$ cd myapp
# 初始化依赖
$ cnpm i
# 安装 multer 模块,用于在服务端接收上传的文件对象
$ cnpm i multer --save
项目创建好以后,需要在项目的根目录下创建 static
的文件夹!
3. 设计上传与下载的服务端路由
在 routes/index.js
中编写以下代码:
var router = require('express').Router();
var multer = require('multer');
var fs = require('fs');
var path = require('path');
//查询文件的路由
router.get('/', function(req, res, next) {
//读取 static 目录下的文件
fs.readdir('./static', function(err, files){
if(err){
res.render('index', {
list: [],
msg: '暂无文件'
})
return
}
res.render('index', {
list: files,
msg: `共有 ${files.length} 个文件`
});
})
});
//删除文件的路由
router.get('/del', function(req,res){
//接收文件名的参数
let {file} = req.query
//删除 static 目录下的该文件
fs.unlink(`./static/${file}`, function(err){
res.redirect('/')
})
})
//文件上传的路由
router.post('/upload', multer({ dest: './static/' }).any(), function(req,res){
let file = req.files[0]
//拼装文件名称
let filename = 'static/'+ file.originalname
//为上传成功的文件重命名(上传的文件默认不是文件的原名称)
fs.rename(file.path, filename, function(err){
res.redirect('/')
})
})
//文件下载的路由
router.get('/down', function(req,res){
//接收文件名称
let {fn} = req.query
//如果参数中有中文,需要解码
fn = decodeURI(fn)
//判断该文件是否存在
fs.access(`./static/${fn}`, function(err){
if(!err){
res.set({
//告诉浏览器这是一个二进制文件
"Content-Type": "application/octet-stream",
//告诉浏览器这是一个需要下载的文件,使用encodeURI方法,是为了避免中文名称下载时出问题
"Content-Disposition": `attachment;filename=${encodeURI(fn)}`
})
//使用流读取文件,并响应给客户端
fs.createReadStream(`./static/${fn}`).pipe(res)
}
})
})
module.exports = router;
4. 设计前端的EJS模板
打开 views/index.ejs
文件,示例代码如下:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1>静态资源管理器</h1>
<!-- 用于上传文件的form表单 -->
<form action="/upload" method="POST" enctype="multipart/form-data" >
<input type="file" name="myfile">
<button type="submit">上传文件</button>
</form>
<hr>
<!-- 文件列表 -->
<div style="color: blue;">
<%= msg %>
</div>
<ul>
<% list.forEach(function(item){ %>
<li style="margin: 10px 0px;">
<%=item%>
<a href="javascript:del('<%=item%>');">删除</a>
<a href="javascript:down('<%=item%>');">下载</a>
</li>
<% }) %>
</ul>
<script>
//删除文件的请求方法
function del(filename){
var result = window.confirm(`确定要删除${filename}吗?`)
if(result){
window.location.href = `/del?file=${filename}`
}
}
//下载文件的请求方法
function down(filename){
var url = `/down?fn=${filename}`
window.location.href = encodeURI(url) //处理中文参数
}
</script>
</body>
</html>