摘要:通过前两天的学习我大概学了了,用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. C#保留小数位数的方法

    1.System.Globalization.NumberFormatInfo provider = new System.Globalization.NumberFormatInfo();provi ...

  2. OpenTSDB介绍

    OpenTSDB 2.0, the scalable, distributed time series database可扩展.分布式时间序列数据库 1.背景 一些老的监控系统,它常常会出现这样的问题 ...

  3. WPF字符串中的换行符

    <sys:String x:Key="NewUpdateWillShow" xml:space="preserve">第一行 第二行 </sy ...

  4. nodejs+mongoose+websocket搭建xxx聊天室

    简介 本文是由nodejs+mongoose+websocket打造的一个即时聊天系统:本来打算开发一个类似于网页QQ类似功能的聊天系统,但是目前只是开发了一个模块功能 --- 类似群聊的,即一对多的 ...

  5. Java爬虫框架WebMagic——入门(爬取列表类网站文章)

    初学爬虫,WebMagic作为一个Java开发的爬虫框架很容易上手,下面就通过一个简单的小例子来看一下. WebMagic框架简介 WebMagic框架包含四个组件,PageProcessor.Sch ...

  6. async await Task

    一.使用Task 引用命名空间 using System.Threading.Tasks; 1.工厂方式 Task.Factory.StartNew(() => {Console.WriteLi ...

  7. iOS APP上架被拒重新提交审核教程

    iOS APP审核比较严格,难免会出现被拒绝的情况,需要根据苹果反馈的问题修改后重新打包上传审核! 1.登录itunesconnect.https://itunesconnect.apple.com进 ...

  8. accept 文件描述符用尽处理

    if (events[i].data.fd == listenfd) { peerlen = sizeof(peeraddr); connfd = ::accept4(listenfd, (struc ...

  9. (译)ABP之依赖注入

    原文地址:https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection 什么是依赖注入 传统方式的问题 解决方案 构造函数注入 ...

  10. 工程启动加载.properties/.xml配置文件

    工程目录: demo.properties today=2017-06-10 PropertiesMap.java package com.dzpykj.common.utils; import ja ...