Node学习入门篇(八):Express

本章内容

  • 开始一个新的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>

完。

猜你喜欢

转载自blog.csdn.net/w_bu_neng_ku/article/details/79961734