摘要:通过前两天的学习我大概学了了,用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) ;
//
app.use(function (req,res) { res.render("err"); });
app.listen();

用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="data: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>

  

用node.js实现mvc相册资源管理器的更多相关文章

  1. node.js express mvc轻量级框架实践

    本文记录的是笔者最近抽私下时间给朋友做的一个时时彩自动下注系统,比较简单,主要也是为了学习一下node.js. 其实逻辑没什么可以深谈的,主要是想说说这套代码结构.结构如下图: js的代码比较难以维护 ...

  2. 转 10 个最佳的 Node.js 的 MVC 框架

    10 个最佳的 Node.js 的 MVC 框架 oschina 发布于: 2014年02月24日 (33评) 分享到:    收藏 +322 Node.js 是一个基于Chrome JavaScri ...

  3. 10 个最佳的 Node.js 的 MVC 框架

    补充:http://nokit.org/ https://thinkjs.org/zh-cn/doc/index.html Node.js 是一个基于Chrome JavaScript 运行时建立的一 ...

  4. 用node搭建简单的静态资源管理器

    我们都知道,老牌的3p服务器都是自带静态资源管理器的.但是node不同,它没有web容器,它的路由地址和真实地址可以没有联系,所有node的优点,是可以把路由做得相当漂亮. 但静态资源管理器也是必不可 ...

  5. Node.js与Sails~方法拦截器policies

    回到目录 policies sails的方法拦截器类似于.net mvc里的Filter,即它可以作用在controller的action上,在服务器响应指定action之前,对这个action进行拦 ...

  6. Node.js+Express+MVC+Mysql小白创建新项目

    1.打开CMD命令窗口,这一步不会的,回家休息,不要看了 2.npm install -g yo  等待时间看个人电脑情况. 如果没有npm命令,建议先安装npm ,npm安装介绍:https://d ...

  7. Node.js 包管理器 NPM 讲解

    包管理器又称软件包管理系统,它是在电脑中自动安装.配制.卸载和升级软件包的工具组合,在各种系统软件和应用软件的安装管理中均有广泛应用.对于我们业务开发也很受益,相同的东西不必重复去造轮子. 每个工具或 ...

  8. Node.js教程系列~目录

    Node.js这个东西在近几年火起来了,而且会一直火下去,无论在infoq还是在cnblogs,csdn上,都可以到处看到它的样子,它主推的应该就是异步式I/O 吧,是的,设计的很完美,很吸引人,虽然 ...

  9. Node.js +Express+MongoDB+mogoose+ejs+bootstrap+jquery

    Node.js + MongoDB 项目实战(二)  创建项目 在项目实战(一)中,已经配置好了开发环境(详见:http://www.cnblogs.com/jameslong/articles/34 ...

随机推荐

  1. HTML知识速递

    1.html的定义 超文本标记语言(Hypertext Markup Language,HTML)通过标签语言来标记要显示的网页中的各个部分.一套规则,浏览器认识的规则 浏览器按顺序渲染网页文件,然后 ...

  2. 【APP问题定位(三)】adb安装

    先来剧透一下我们需要使用的工具 bin包               一个安装目录,可以免安装直接调用adb命令 Android SDK platform tools 下面依次为大家介绍,第1个和第2 ...

  3. 插件lombok的介绍安装

    Lombok插件 介绍一个不错的Eclipse插件Lombok 该插件对Log4j简化的代码,因为不大,所以jar包也存在呢! Lombox是Eclipse的一个插件,用来自动生成Java代码,减少手 ...

  4. Python 动态添加类方法

    习题: 1. Shape基类,要求所有子类都必须提供面积的计算,子类有三角形.矩形.圆. 2. 上题圆类的数据可序列化 第一种方法:使用Mixin多继承组合的方式,混入其它类的属性和方法 第二种方法: ...

  5. python常用数据结构

    0. 字典初始化 d = {'a':1,'b':2} 或 d={} d['a'] = 1 d['b'] = 2 是不是和json格式数据很相似,语法和JavaScript又很相似 1. 变量接受序列分 ...

  6. 一些常用软件的静默安装参数(nsis,msi,InstallShield,Inno)

    打包的时候,经常需要安装一些其它的环境库,而又不想让用户繁锁的去选择,这时就需要静默安装,而不同的文件所加的参数了不一致,比如VS的环境库vcredist_x86.exe(这是32位的环境库)后面加/ ...

  7. 如何使用MFC连接Access数据库

    (1)新建一个Access数据库文件.将其命名为data.mdb,并创建好表.字段. (2)为系统添加数据源.打开“控制面板”—>“管理工具”—>“数据源”,选择“系统DSN”,点击右边的 ...

  8. js 事件冒泡和事件捕获

    事件流:指的是网页中元素接受事件的顺序,它是一个概念,而不是具体的实际的东西 事件冒泡:指的是内层元素的事件,会触发包含着此元素的外层元素的事件,触发的顺序是:由内而外的 例如: <!DOCTY ...

  9. 一个web图片热点生成工具(winform开发) 附源码

    给图片加热点是web开发中经常用到的一个功能.这方面的工具也不少. 为了更好的满足自己的需求,写了一个winform程序. 可以方便的给图片加热点,更方便灵活! 源码下载 http://downloa ...

  10. caioj 1236 最近公共祖先 树倍增算法模版 倍增

    [题目链接:http://caioj.cn/problem.php?id=1236][40eebe4d] 代码:(时间复杂度:nlogn) #include <iostream> #inc ...