zoukankan      html  css  js  c++  java
  • 用node.js实现mvc相册资源管理器

    摘要:通过前两天的学习我大概学了了,用formidable模块文件上传,express框架,以及利用fs模块进行文件读取,今天我学习了如何用这些知识来制作相册,暂没有数据库,所以做的也是本地的资源管理器。根据本地存放照片文件夹,通过服务器来进行查看本地照片文件夹和上传照片到该文件夹

    一、成品展示:

     二、总体设计

     三、实现代码

    app.js

    var express=require("express");
    var app=express();
    //控制器
    var router=require("./controller");        //在package.json里设置了router.js为默认的js
    //设置模版引擎
    app.set("view engine","ejs");
    
    //路由中间件
    //静态页面
    app.use(express.static('./public'));
    app.use(express.static('./uploads'));
    //get/的时候,上层函数回调的时候传入req,res
    //首页 app.get("/",router.showIndex);
    app.
    get("/up", router.showUp);
    app.
    get('/:albumName',router.showAlbum);
    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) {
        //错误的:传统的思维不是node的思维
        // res.render("index",{
      //注意这里异步的,遇到阻塞,会直接呈递模版引擎,所以这种写法是错误的,小函数会没执行完,就呈递
        //     "albums":file.getAllAlbums()
        // });
    
        //这就是node.js的编程思维,就是所有的东西,都是异步的
        //所以,内层函数,不是return回来东西,而是调用高层函数提供的
        //回调函数。把数据当成回调函数的参数来使用
        file.getAllAlbums(function (err,allAlabums) {      //这个函数就是callback
            //err是字符串
            if(err){
                res.send(err);
                return ;
            }
            res.render("index",{
                "albums":allAlabums
            });
        });
    }
    
    //相册页
    exports.showAlbum=function (req,res) {
        //遍历相册中的所有图片
        var albumName=req.params.albumName;
        //具体业务交给model
        file.getAllImagesByAlbumName(albumName,function (err,imagesArray) {
            if(err){
                res.send(err);
                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");          //上传到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>2000){
                res.send("图片尺寸应该小于1M");
                //删除图片
                fs.unlink(files.tupian.path);
                return ;
            }
          //加时间戳
    var ttt=sd.format(new Date(),"YYYYMMDDHHmmss"); var ran=parseInt(Math.random()*89999+10000); var extname=path.extname(files.tupian.name); var wenjianjia=fields.wenjianjia; var oldpath=files.tupian.path; var newpath=path.normalize(__dirname+"/../uploads/"+wenjianjia+'/'+ ttt + ran + extname); fs.rename(oldpath,newpath,function(err){ if(err){ res.send('改名失败'); return; } res.send("成功"); }); }); return; }

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

     file.js

    var fs=require("fs");
    
    //这个函数的callback中含有两个参数,一个是err
    //另一个是存放所有文件夹名字的array
    exports.getAllAlbums=function (callback) {
        fs.readdir("./uploads", function (err, files) {
            if (err){
                callback("没有找到uploads子文件夹",null);
            }
            var allAlbums = [];
            console.log(files);
            (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("没有找到uploads文件",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.ejs

    <!DOCTYPE html>
    <html>
    <head>
        <title>小小相册</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
        <style>
            .row h4{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <!--<h1>小小相册</h1>-->
    <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>
    
                </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/wjj.jpg" alt="...">
                    </a>
                    <h4><%=albums[i]%></h4>
                </div>
                 <%}%>
            </div>
    
        </div>
    
    <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>小小相册</title>
        <link href="/css/bootstrap.min.css" rel="stylesheet">
        <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><a href="/">全部相册<span class="sr-only">(current)</span></a></li>
                    <li><a href="/up">上传</a></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]%>" alt="...">
                </a>
                <h4> </h4>
            </div>
            <%}%>
        </div>
    </div>
    
    <script src="/js/jquery-1.11.3.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    </body>
    </html>

    上传页:up.ejs

    <!DOCTYPE html>
    <html>
    <head>
        <title>小小相册</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
        <style>
            .row h4{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <!--<h1>小小相册</h1>-->
    <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="#">上传</a></li>
    
                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    
    <div class="container">
        <div class="row">
            <form method="post" action="#" enctype="multipart/form-data">
                <div class="form-group">
                    <label for="exampleInputEmail1">选择文件夹</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>
                    <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">Submit</button>
            </form>
        </div>
    
    </div>
    
    <script src="/js/jquery-1.11.3.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    </body>
    </html>

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

     错误页面:err.ejs

    <!DOCTYPE html>
    <html>
    <head>
        <title>小小相册</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
        <style>
            .row h4{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <!--<h1>小小相册</h1>-->
    <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="#">上传</a></li>
    
                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    
    <div class="container">
    
        <img src="<%=baseurl%>/images/404.jpg" alt="">
    </div>
    
    <script src="/js/jquery-1.11.3.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    </body>
    </html>

      

  • 相关阅读:
    codevs1430 素数判定
    codevs1212 最大公约数
    codevs1012 最大公约数和最小公倍数问题
    codevs1160 蛇形矩阵
    Debate CodeForces
    Divide Candies CodeForces
    Login Verification CodeForces
    Colorful Bricks CodeForces
    ExaWizards 2019 English D
    Cards and Joy CodeForces
  • 原文地址:https://www.cnblogs.com/15fj/p/8116508.html
Copyright © 2011-2022 走看看