摘要:通过前两天的学习我大概学了了,用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. [转载] Thrift-client与spring集成

    转载自http://shift-alt-ctrl.iteye.com/blog/1990030?utm_source=tuicool&utm_medium=referral Thrift-cl ...

  2. Android Oreo 8.0 新特性实战 Autosizing TextView --自动缩放TextView

    Android Oreo 8.0 新特性实战 Autosizing TextView --自动缩放TextView 8.0出来很久了,这个新特性已经用了很久了,但是一直没有亲自去试试.这几天新的需求来 ...

  3. iOS开发经验总结

    总结了几个月的东西终于能和大家分享了,不多说,直接看东西! 1.禁止手机睡眠 1 [UIApplication sharedApplication].idleTimerDisabled = YES; ...

  4. Python 爬虫练习(三) 利用百度进行子域名收集

    不多介绍了,千篇一律的正则匹配..... import requests import re head = {'User-Agent': \ 'Mozilla/5.0 (Windows NT 6.3; ...

  5. python常用数据结构

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

  6. 学习MySQL(下)

    具体实例 22.MySQL ALTER命令 当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令. 1.如果需要修改数据表的名称,可以在 ALTER TABLE 语句中使 ...

  7. windows下tensorflow的安装

    一.直接python安装 1.CPU版本: pip3 install --upgrade tensorflow 2.GPU版本:pip3 install --upgrade tensorflow-gp ...

  8. 三种方法运行python

    注:本文基于windows 1.交互式解释器 配置好环境变量后,命令行中打开,输入python即可,Ctrl+Z退出 命令行选项 当从命令行启动Python时,可以给解释器一些选项,如下: -d   ...

  9. NodeJS网络爬虫

      原文地址:NodeJS网络爬虫   网上有很多其他语言平台版本的网络爬虫,比如Python,Java.那怎么能少得了我们无所不能的javascript呢

  10. ML笔记:Where does the error come from?

    error来自哪? 来自于偏差Bias和方差Variance. 就如打靶时瞄准一个点f平均,打出的点f星分布在该点周围. 该点与实际靶心f帽的距离就是偏差Bias, 打出的点与该点的分布距离就是方差V ...