码迷,mamicode.com
首页 > Web开发 > 详细

Node 实现一个MVC相册资源管理器

时间:2017-11-20 23:13:22      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:语句   field   分享   应该   center   后台   ams   lis   alt   

暂没有数据库,所以做的也是本地的资源管理器。

技术分享图片

 

技术分享图片

技术分享图片

总体设计:

 

技术分享图片

 

 

 app.js:

var express = require("express");

var app = express();
//控制器
var router = require("./controller");
//设置模版引擎
app.set("view engine","ejs");

//路由中间件
//静态页面
app.use(express.static("./public"));
app.use(express.static("./uploads"));
//get/的时候,上层函数回调的时候传入req,res
//首页
app.get("/",router.showIndex);
app.get("/:albumName",router.showAlbum);
app.get("/up",router.showUp);
app.post("/up",router.doPost);
//404
app.use(function (req,res) {
    res.render("err");
});
app.listen(3000);

用express静态出public和uploads文件夹,用来放资源文件,然后分别路由主页,相册文件夹,上传页面,上传表单处理。

 

然后在控制层的controller来控制前台和后台的交互

router.js:

var file = require("../models/file.js");
var formidable = require("formidable");
var path = require("path");
var fs = require("fs");
var sd = require("silly-datetime");
exports.showIndex = function (req,res,next) {
    //错误的,传统的思维,不是Node的思维。
    // res.render("index",{
    //     //注意这里异步的,遇到阻塞,会直接呈递模版引擎,所以这种写法是错误的,小函数会没执行完,就呈递了
    //     "albums" : file.getAllAlbums()
    // });
    //这就是Node.js的编程思维,就是所有的东西,都是异步的
    //所以,内层函数,不是return回来东西,而是调用高层函数提供的
    //回调函数。把数据当做回调函数的参数来使用。
    file.getAllAlbums(function (err,allAlbums) { //这个function就是callback
        //err是字符串
        if(err) {
            next();
            return;
        }
        res.render("index",{
            "albums" : allAlbums
        });
    })
};

//相册页
exports.showAlbum = function (req,res,next) {
    //遍历相册中的所有图片
    var albumName = req.params.albumName;
    //具体业务交给model
    file.getAllImagesByAlbumName(albumName,function (err,imagesArray) {
        if(err) {
            next();
            return;
        }
        res.render("album",{
            "albumname" : albumName,
            "images" : imagesArray
        });
    });
    
};

exports.showUp = function (req,res) {
    //命令file模块(我们自己写的函数)调用getAllAlbums函数
    //得到所有文件夹名字之后做的事情,写在回调函数里面
    file.getAllAlbums(function (err,albums) {
        res.render("up",{
            albums : albums
        });
    })
}

//上传表单
exports.doPost = function (req,res) {
    var form = new formidable.IncomingForm();

        // "../"返回上一级
    form.uploadDir = path.normalize(__dirname + "/../tempup/");
    form.parse(req, function (err, fields, files,next) {
        console.log(fields);
        console.log(files);
        //改名
        if(err) {
            next(); //这个中间件不受理这个请求了,往下走
            return;
        };

        //判断文件尺寸
        var size = parseInt(files.tupian.size);
        if(size > 2000000) {
             res.send("图片尺寸应该小于2M");

            //则删除这个文件
            fs.unlink("files.tupian.path",function () {

            });
            return;
        }
        var wenjianjia = fields.wenjianjia;
        var oldpath = files.tupian.path ;
        //还是加时间戳
        var ttt = sd.format(new Date(), "YYYMMDDHHmmss");
        var ran = parseInt(Math.random() * 89999 + 10000);
        var extname = path.extname(files.tupian.name);
        var newpath = path.normalize(__dirname + "/../uploads/" + wenjianjia + "/" + ttt + ran + extname);
        fs.rename(oldpath,newpath,function (err) {
            if(err) {
                res.send("改名失败");
                return;
            }
            res.send("成功");
        });
    });


}

 

底层的真正处理的模型层的file.js,注意的是由于这里没用es6的先进写法,所以很多是异步语句,正常的return返回是不行的,需要递归迭代来获得所有数据,用callback回调处理

var fs = require("fs");

//这个函数的callback中含有两个参数,一个是err
//另一个是存放所有文件夹名字的array。
exports.getAllAlbums = function (callback) {
    fs.readdir("./uploads", function (err,files) {
        if(err) {
            callback("没有找到upload文件",null);
        }
        var allAlbums = [];
        (function iterator(i) {
            if (i == files.length) {
                //遍历结束
                console.log(allAlbums);
                //执行完了之后,执行回调函数
                callback(null,allAlbums);
                return;
            }

            fs.stat("./uploads/" + files[i], function (err, stats) {
                if(err) {
                    callback("找不到文件" + files[i],null);
                }
                if (stats.isDirectory()) {
                    allAlbums.push(files[i]);
                }
                iterator(i + 1);
            });
        })(0);
    });
}

//通过文件名,得到所有图片
exports.getAllImagesByAlbumName = function (albumName,callback) {
    fs.readdir("./uploads/" + albumName, function (err,files) {
        if(err) {
            callback("没有找到upload文件",null);
            return;
        }
        var allImages = [];
        (function iterator(i) {
            if (i == files.length) {
                //遍历结束
                console.log(allImages);
                //执行完了之后,执行回调函数
                callback(null,allImages);
                return;
            }

            fs.stat("./uploads/" + albumName + "/" + files[i], function (err, stats) {
                if(err) {
                    callback("找不到文件" + files[i],null);
                    return;
                }
                if (stats.isFile()) {
                    allImages.push(files[i]);
                }
                iterator(i + 1);
            });
        })(0);
    });
}

 剩下的就是view视图层的前端样式了,用的ejs模板和bootstrap样式:

主页index.js:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>littleAlbum</title>

    <link href="css/bootstrap.min.css" rel="stylesheet">

    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <style type="text/css">
        .row h4 {
            text-align: center;
        }
    </style>
</head>
<body>

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">小小相册</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">全部相册 <span class="sr-only">(current)</span></a></li>
                <li><a href="up">上传</a></li>
                <li class="dropdown">
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

<div class="container">
    <div class="row">
        <% for(var i = 0; i < albums.length; i++){ %>
        <div class="col-xs-6 col-md-3">
            <a href="<%= albums[i] %>" class="thumbnail">
                <img src="images/wenjianjia2.jpg" alt="...">
            </a>
            <h4><%= albums[i] %></h4>
        </div>
        <% } %>
    </div>
</div>
<!--运行之后views和public是在一起的-->
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</body>
</html>

相册页album.ejs:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>littleAlbum</title>

    <link href="/css/bootstrap.min.css" rel="stylesheet">

    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <style type="text/css">
        .row h4 {
            text-align: center;
        }
    </style>
</head>
<body>

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">小小相册</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">全部相册 <span class="sr-only">(current)</span></a></li>
                <li><a href="/up">上传</a></li>
                <li class="dropdown">
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>



<div class="container">

    <ol class="breadcrumb">
        <li><a href="/">全部相册</a></li>
        <li class="active"><%= albumname %></li>
    </ol>
    <div class="row">
        <% for(var i = 0; i < images.length; i++){ %>
        <div class="col-xs-6 col-md-3">
            <a href="#" class="thumbnail">
                <img src="<%= images[i] %>" >
            </a>
            <h4></h4>
        </div>
    </div>
    <% } %>
</div>
<!--运行之后views和public是在一起的-->
<script src="/js/jquery-1.11.3.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>

up.ejs:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>小小相册</title>

    <link href="/css/bootstrap.min.css" rel="stylesheet">

    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <style type="text/css">
        .row h4 {
            text-align: center;
        }
    </style>
</head>
<body>

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">小小相册</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">全部相册 <span class="sr-only">(current)</span></a></li>
                <li><a href="up">上传</a></li>
                <li class="dropdown">
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

<div class="container">
    <div class="row">
        <form style = "width: 40%" method="post" enctype="multipart/form-data" action = "#">
            <div class="form-group">
                <label for="exampleInputFile">选择文件夹</label>
                <select class="form-control" name = "wenjianjia">
                    <% for(var i = 0; i < albums.length; i++) {%>
                    <option><%= albums[i] %></option>
                    <%}%>
                </select>
            </div>

            <div class="form-group">
                <label for="exampleInputFile">选择图片</label>
                <p>尺寸小于2M</p>
                <input type="file" id="exampleInputFile" name = "tupian">
                <p class="help-block">Example block-level help text here.</p>
            </div>

            <button type="submit" class="btn btn-default">上传</button>
        </form>
    </div>
</div>
<!--运行之后views和public是在一起的-->
<script src="/js/jquery-1.11.3.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>

err.ejs:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>littleAlbum</title>

    <link href="/css/bootstrap.min.css" rel="stylesheet">

    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <style type="text/css">
        .row h4 {
            text-align: center;
        }
    </style>
</head>
<body>

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">小小相册</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">全部相册 <span class="sr-only">(current)</span></a></li>
                <li><a href="up">上传</a></li>
                <li class="dropdown">
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

<div class="container">
    <img src="/images/404.jpg" >
</div>
<!--运行之后views和public是在一起的-->
<script src="/js/jquery-1.11.3.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>

注意上传模块用的formidable,获得的files,fields对象参数,是和表单标签样式name属性对应的。

Node 实现一个MVC相册资源管理器

标签:语句   field   分享   应该   center   后台   ams   lis   alt   

原文地址:http://www.cnblogs.com/zhangmingzhao/p/7868421.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!