本章内容
- 开始一个新的Express程序
- 配置你的程序
- 创建Express视图
- 处理文件上传和下载
Express
1.生成项目
- 全局安装
npm install -g express
生成项目
express -e projectName
执行npm install
2.环境配置
环境驱动配置
Express有一个极简的环境驱动配置系统,由5个方法组成,全部由环境变量NODE_ENV驱动
- app.configure()
- app.set()
- app.get()
- app.enable()
- app.disable()
1)设置环境变量
要在UNIX中设置环境变量,可以用这个命令:$ NODE_ENV=production node app
在Windows中用这个:
$ set NODE_ENV=production $ node app
这些环境变量会出现在你程序里的process.env对象中
2) app.configure()方法接受一个表示环境的可选字符串,以及一个函数,app.configure()只是糖衣而已,实际上可不比使用这个特性。
3) Express还为Boolean类型的配置项提供了app.set()和app.get()的变体
3. 视图渲染
视图渲染
- 数据传给视图,然后数据会被转换,通常是变成Web程序中的HTML
- Express中两种渲染视图的办法
- 在程序层面用
app.render()
,在请求或响应层面用res.render()
,它在内部用的也是前者
1)配置视图查找目录
app.set('views', path.join(__dirname, 'views'));
2)设置视图引擎
视图引擎使得在使用视图的时候不需要指定扩展名,如果没有设置,需要指定扩展名,Express才能确定使用哪个。app.set('view engine', 'ejs');
3)视图缓存
启动视图缓存后,模板的内容保存在内存中,下次请求会查找缓存,从缓存中获取,减少了硬盘I/O的执行,提高了性能。如果被禁用,则每次都要执行I/O。
4) 视图查找
先查找绝对路径,再查找视图设置的指定目录,如果都没有,最后,Express会尝试使用index,如果也没有,那么报错。
5)输出数据到视图
添加视图模板
<!DOCTYPE html>
<html>
<head>
<title><%=title %></title>
<link rel="stylesheet" href="/stylesheets/photos.css"></li>
</head>
<body>
<h1> Photos </h1>
<div id="photos">
<% photos.forEach(function(photo) { %>
<div class="photo">
<h2><%=photo.name%></h2>
<image src='<%=photo.path%>'/>
</div>
<% }) %>
</div>
</body>
</html>
css
body {
padding: 50px;
}
a {
color: #00B7FF;
}
.photo {
display: inline-block;
margin:5px;
padding: 10px;
width: 250px;
height: 200px;
box-shadow: 0 1px 2px #ddd;
border-radius: 5px;
text-align: center;
}
.photo h2 {
font-size: 14px;
font-weight: 200;
}
.photo img {
height: 150px;
width: 180px;
}
路由:
var express = require('express');
var router = express.Router();
var photos = [];
photos.push({
name:'love',
path:'https://timgsa.baidu.com/timg?image
&quality=80&size=b9999_10000&sec=1524453697
&di=64e2117ccd33d34857d369c8afc58c8c&imgtype=jpg
&er=1&src=http%3A%2F%2Fimg.taopic.com
%2Fuploads%2Fallimg%2F121019%2F234917-121019231h258.jpg'
});
photos.push({
name:'grass',
path:'https://timgsa.baidu.com/timg
image&quality=80&size=b9999_10000&sec=1523859025529
&di=b76d2e6d14fa394d5d54ee7f1da38ad3&imgtype=0
&src=http%3A%2F%2Fimg03.tooopen.com%2Fuploadfile
%2Fdowns%2Fimages%2F20110714%2Fsy_20110714135215645030.jpg'
})
router.get('/', function(req, res) {
res.render('photos',{
title:'photos',
photos:photos
});
});
module.exports = router;
访问localhost:3000, 效果:
4.处理表单和文件上传
- MondoDB存储
安装好MongoDB,使用mongoose 作为驱动,给项目安装mongoose 。
npm install mongoose --save
- 连接数据库并创建模型
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/photo_app');
var schema = new mongoose.Schema({
name:String,
path:String
});
module.exports = mongoose.model('Photo', schema)
- 创建表单上传
<!DOCTYPE html>
<html>
<head>
<title><%=title %></title>
<link rel="stylesheet" type="text/css" href="/stylesheets/photos.css"></li>
</head>
<body>
<h1> Photos </h1>
<div id="photos">
<% photos.forEach(function(photo) { %>
<div class="photo">
<h2><%=photo.name%></h2>
<image src='<%=photo.path%>'/>
</div>
<% }) %>
</div>
<div id="upload">
<form method="post" enctype="multipart/form-data" action="/">
<p><input type="text" name='name' placeholder="Name"></p>
<p><input type="file" name="image"></p>
<p><input type="submit" value="Upload"></p>
</form>
</div>
</body>
</html>
- 编写路由
exports.submit = function(dir) {
return function(req, res, next) {
//使用formidable解析
var form = new formidable.IncomingForm();
//上传到服务器的目录,指定这个目录,否则可能存在跨磁盘区域读写的错误
form.uploadDir = dir;
//保留后缀名
form.keepExtensions = true;
form.encoding = 'utf-8';
form.parse(req, function(err, fields, files) {
if(err) return res.redirect('/');
console.log(fields);
console.log(files);
var img = files.image;
var name = fields.name || img.name;
var newPath = join(dir, img.name);
var imageSrc = '/images/' + img.name;
fs.rename(img.path, newPath, function(err) {
if(err) return next(err);
Photo.create({
name:name,
path:imageSrc
}, function(err) {
if(err) return next(err);
res.writeHead(200, {'contentType':'application/json'});
res.end(JSON.stringify({'success':true}));
})
});
});
};
};
- 添加路由
app.get('/', photoRouter.list);
app.post('/', photoRouter.submit(app.get('photos')));
- 解析表单需要添加中间件
可选body-parser或formidable
npm install formidable
- 效果
几点需要注意的:
1) enctype
<form method="post" enctype="multipart/form-data" action="/">
2) 显示图片所需要的路径,采用相对路径!
var imageSrc = '/images/' + img.name;
创建资源下载
- static提供静态资源
//提供./public下的静态资源
app.use(express.static(path.join(__dirname, 'public')));
Express提供了几种处理文件传输的响应方法:
- 传送文件的res.sendfile()
- 它的变体res.download()
创建图片下载路由
exports.download = function(dir) {
return function(req, res, next) {
console.log(req.params);
var id = req.params.id;
Photo.findById(id, function(err, photo) {
if(err) return next(err);
var path = join(dir, photo.path.substr(7));
// res.sendfile(path);
//使用download才会触发浏览器下载
res.download(path, photo.name+'.jpeg');
});
};
};
- 给图片点击下载
<div class="photo">
<h2><%=photo.name%></h2>
<a href="/photo/<%=photo.id%>/download">
<image src='<%=photo.path%>'/>
</a>
</div>
完。