业务简介:

显示文件夹

点击显示相册

上传相册

一、在主页显示文件夹

 首先,我们要建立以上的文件夹,其中views用于放模板ejs,uploads里放的是相册文件夹,public是网页所需要的css,js等,node_modules放的是开发要用到的包,models是为数据库而建立的(本次用不到数据库)里面的函数是最底层的,tempup只是用于图片上传时的中转站(之后会懂的),controller文件夹里就是真正需要实现业务的函数。

 

1.在app.js里使用express

var express = require("express");
var app = express();
//控制器
var router = require("./controller"); //设置模板引擎
app.set("view engine","ejs"); //路由中间件
//静态页面
//app.use("/static",express.static("./public"));//所有/static/是从public下找
app.use(express.static("./public"));
app.use(express.static("./uploads")); app.get("/",router.showIndex);//函数的引用
app.listen(3000);
这一句表示当开启网页 http://localhost:3000/ 时,将调用router里的showIndex
app.get("/",router.showIndex);//函数的引用 

2. 在router里需要写showIndex函数,函数中,通过调用file,js里的getAllAlbums函数获得allAlbums数组,再将数组给allAlbums,同时渲染前端页面index.ejs,其中ejs可不写

var file = require("../models/file")
//用于文件操作
var fs = require("fs"); //首页
exports.showIndex = function (req,res,next) {
//传统的思维,错误的
/*res.render("index",{ //由于异步不能这么写,还没return就已经赋值了
"albums":file.getAllAlbums()
});*/
//这就是Node.js的编程思维,就是所有东西都是异步的
//所以,内侧函数,不是return回来东西,而是调用高层函数
//提供的回调函数,把数据当作回调函数的参数来使用。
file.getAllAlbums(function (err,allAlbums) {
if(err){
next();//交给下面适合它的中间件
//res.render("err");
return;
}
res.render("index",{
"albums":allAlbums
})
})
}

 3.接着我们在models文件下建立file.js,在里面写getAllAlbums函数,用于获取uploads文件夹下的所有文件夹,借用迭代器组成一个数组allAlbums返回。

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);
//return allAlbums;//遍历结束
callback(null,allAlbums);
return;
}
fs.stat("./uploads/"+files[i],function (err,stats) {
if(err){
callback("找不到文件"+files,null);
}
if(stats.isDirectory()){
allAlbums.push(files[i]);
}
iterator(i +1);
})
})(0);
});
}

 4.最后,要写模板函数index.ejs,在views下新建一个index.ejs,利用bootstrap写模板,这里时关键。因为我们已将public静态了,也就是public里的东西都公开了。所以这里直接images/图片即可

<!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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>小小相册</title> <!-- Bootstrap -->
<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 class="active"><a href="/">全部相册 <span class="sr-only"></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> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>

二、404页面的制作

1.在views下新建一个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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>小小相册</title> <!-- Bootstrap -->
<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"></span></a></li>
<li><a href="/up">上传</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav> <div class="container">
<img src="/images/404.gif"/>
</div> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="/js/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="/js/bootstrap.min.js"></script>
</body>
</html>

2.再在app.js下配置路由

三、点击相册文件夹,显示所有图片

1.先配置路由

app.get("/:albumName",router.showAlbum);

2.在router.js里写函数showAlbum,要通过向file.js里写函数getAllImagesByAlbumName传相册名获得该相册的所有图片路径,再传给前端album.ejs

//相册页
exports.showAlbum = function (req,res,next) {
//遍历相册页的所有图片
var albumName = req.params.albumName;
//具体业务交给model //调用函数得到图片
file.getAllImagesByAlbumName(albumName,function(err,imagesArray){
//返回得到imagesArray
if(err){
next();//交给下面适合它的中间件
//res.render("err");
return;
}
//渲染album.ejs页面,把albumname赋值albumName传到页面
res.render("album",{
"albumname":albumName,
"images":imagesArray
});
});
}

3.在models里的file.js里写函数getAllImagesByAlbumName,利用router里传来的相册名,获取所有图片路径

//通过文件名,得到所有图片
exports.getAllImagesByAlbumName = function (albumName,callback) {
fs.readdir("./uploads/"+albumName,function (err,files) {
if(err){
callback("没有找到uploads文件夹",null);
return;
}
var allImages = [];
//console.log(files);//[ '小狗', '军犬' ] //迭代器 异步
(function iterator(i) {
if(i == files.length){
//console.log(allImages);
//return allAlbums;//遍历结束
callback(null,allImages);
return;
}
fs.stat("./uploads/"+albumName+"/"+files[i],function (err,stats) {
if(err){
callback("找不到文件"+files,null);
return;
}
if(stats.isFile()){
allImages.push(files[i]);
}
iterator(i +1);
})
})(0);
})
}

4.写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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>小小相册</title> <!-- Bootstrap -->
<link href="/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
.row h4{
text-align: center;
}
.thumbnail img{
width:auto;
height: auto;
}
</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"></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>
</div>
<%}%>
</div>
</div> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="/js/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="/js/bootstrap.min.js"></script>
</body>
</html>

5.记得最后把超链接都补补全

四、上传相册

1.先配置路由,做一个上传的界面

app.js全部代码:

var express = require("express");
var app = express();
//控制器
var router = require("./controller"); //设置模板引擎
app.set("view engine","ejs"); //路由中间件
//静态页面
//app.use("/static",express.static("./public"));//所有/static/是从public下找
app.use(express.static("./public"));
app.use(express.static("./uploads")); 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);

2.在router里写showUp和doPost函数

showUp比较简单,就是跳转到up.ejs页面,同时该页面有个下拉框,需要显示所有相册文件夹的名字

doPost比较复杂,它先将上传的文件放到了tempup文件夹里,然后利用fs自带函数rename改名,新名字使用了上传的时间戳。改名的同时,可以更改文件路径。再将文件上传的过程中,先判断图片的大小有没有超限,超的话使用fs自带的unlink函数删除。

 

router.js全部代码

var file = require("../models/file")
//npm install silly-datetime 用于上传使用
var formidable = require('formidable');
var path = require("path");
//用于文件操作
var fs = require("fs");
//npm install silly-datetime 用于获取日期
var sd = require("silly-datetime"); //首页
exports.showIndex = function (req,res,next) {
//传统的思维,错误的
/*res.render("index",{ //由于异步不能这么写,还没return就已经赋值了
"albums":file.getAllAlbums()
});*/
//这就是Node.js的编程思维,就是所有东西都是异步的
//所以,内侧函数,不是return回来东西,而是调用高层函数
//提供的回调函数,把数据当作回调函数的参数来使用。
file.getAllAlbums(function (err,allAlbums) {
if(err){
next();//交给下面适合它的中间件
//res.render("err");
return;
}
res.render("index",{
"albums":allAlbums
})
})
} //相册页
exports.showAlbum = function (req,res,next) {
//遍历相册页的所有图片
var albumName = req.params.albumName;
//具体业务交给model //调用函数得到图片
file.getAllImagesByAlbumName(albumName,function(err,imagesArray){
//返回得到imagesArray
if(err){
next();//交给下面适合它的中间件
//res.render("err");
return;
}
//渲染album.ejs页面,把albumname赋值albumName传到页面
res.render("album",{
"albumname":albumName,
"images":imagesArray
});
});
} exports.showUp = function (req,res) {
//调用file的getAllAlbums函数,得到文件夹名字之后的事情卸载回调函数里
file.getAllAlbums(function (err,allAlbums) {
if(err){
next();//交给下面适合它的中间件
//res.render("err");
return;
}
res.render("up",{
"albums":allAlbums
})
})
} //上传表单
exports.doPost = function (req,res) {
var form = new formidable.IncomingForm(); form.uploadDir = path.normalize(__dirname + "/../tempup/");
console.log(__dirname + "/../temup/") form.parse(req,function (err,fields,files) {
console.log(fields);
console.log(files);
/*res.writeHead(200,{'content-type':'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields,files:files}));*/
//改名
if(err){
next(); //这个中间件不受理这个请求了,往下走
return;
}
//判断文件尺寸
var size = parseInt(files.tupian.size);
if(size>102400){
//console.log("图片尺寸应该小于100M");
res.send("图片尺寸应该小于100M");
//删除图片
fs.unlink(files.tupian.path,function(){});//新版本要加function(){}
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("改名失败");
//console.log("改名失败!")
return;
}
res.send("成功");
});
});
}

3.写up.ejs,在views里新建up.ejs

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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>小小相册</title> <!-- Bootstrap -->
<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"></span></a></li>
<li class="active"><a href="/up">上传</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav> <div class="container">
<div class="row">
<form style="width:40%;" 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">
</div>
<button type="submit" class="btn btn-default">上传</button>
</form>
</div>
</div> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>

 4.最终实现功能

初学nodejs express小案例——小小相册(不涉及数据库,非常详细)的更多相关文章

  1. nodejs+express+mysql 增删改查

    之前,一直使用的是nodejs+thinkjs来完成自己所需的项目需求,而对于nodejs中另外一中应用框架express却了解的少之又少,这两天就简单的了解了一下如何使用express来做一些数据库 ...

  2. nodejs学习篇 (1)webstorm创建nodejs + express + jade 的web 项目

    之前简单了解过nodejs,觉得用nodejs来做个网站也太麻烦了,要自己拼html的字符串返回,这能做网站嘛? 最近看到使用jade模板来开发,觉得挺新奇的,于是试了一把,也了解了一些特性,算是个新 ...

  3. Ubuntu下搭建NodeJS+Express WEB开发框架

    Ubuntu下搭建NodeJS+Express WEB开发框架 2012-12-27 15:06 作者: NodeJSNet 来源: 本站 浏览: 2,966 次阅读 我要评论暂无评论 字号: 大 中 ...

  4. webstorm创建nodejs + express + jade 的web 项目

    webstorm创建nodejs + express + jade 的web 项目 前简单了解过nodejs,觉得用nodejs来做个网站也太麻烦了,要自己拼html的字符串返回,这能做网站嘛? 最近 ...

  5. 用Nodejs+Express搭建web,nodejs路由和Ajax传数据并返回状态,nodejs+mysql通过ajax获取数据并写入数据库

    小编自学Nodejs,看了好多文章发现都不全,而且好多都是一模一样的 当然了,这只是基础的demo,经供参考,但是相信也会有收获 今天的内容是用Nodejs+Express搭建基本的web,然后呢no ...

  6. jquery mobile小案例

    ---恢复内容开始--- [jquery mobile小案例]效果图如下: 首先先创建一个页面主要使用data-role="page"这个指令,我们给它起个id="pag ...

  7. MVC 小案例 -- 信息管理

    前几次更新博客都是每次周日晚上到周一,这次是周一晚上开始写,肯定也是有原因的!那就是我的 Tomact 忽然报错,无法启动,错误信息如下!同时我的 win10 也崩了,重启之后连 WIFI 的标志也不 ...

  8. nodejs+express+socket.io

    其实官网文档清楚了  https://socket.io/get-started/chat/ 但是因为之前写的是nodejs+express, socket.io是后加的, 还是有小坑 服务器端: 官 ...

  9. node.js(小案例)_实现学生信息增删改

    一.前言 本节内容主要对小案例做一个总结: 1.如何开始搭建小项目 2.路由设计 3.模块应用 4.项目源码以及实现过程github地址: 项目演示如下: 二.主要内容 1.项目的关键性js源码: 项 ...

随机推荐

  1. centos7 增加开放端口

    添加 firewall-cmd --zone=public --add-port=80/tcp --permanent (--permanent永久生效,没有此参数重启后失效) 重新载入 不然不生效 ...

  2. 远程连接MySQL提示“Host is not allowed to connected to this MySQL server”

    如果你想连接你的mysql的时候发生这个错误: ERROR 1130: Host '192.168.1.3' is not allowed to connect to this MySQL serve ...

  3. *Bootstrap系列 - (1)概述

    参考 [1] v3.bootcss.com

  4. HelloPlatform

    #include <stdio.h> int main() { #if _PLATFORM_ == _PLATFORM_TRU64 printf("Hello _PLATFORM ...

  5. 高性能MySQL(一)——索引

    一.mysql索引分类 单值索引:一个索引只包含单个列,一个表可以有多个单列索引 唯一索引:索引列的值必须唯一,但允许有空值 复合索引:一个索引包含多个列 基本语法: 创建:1.CREATE [UNI ...

  6. swift是面向对象、面向协议、高阶类型、灵活扩展、函数式编程语言

    swift是面向对象.面向协议.高阶类型.灵活扩展.函数式编程语言

  7. Insecure Code Management

    Insecure Code Management-------------不安全的代码管理 Get the password (in clear text) from the admin accoun ...

  8. pipelinewise 学习二 创建一个简单的pipeline

    pipelinewise 提供了方便的创建简单pipeline的命令,可以简化pipeline 的创建,同时也可以帮我们学习 生成demo pipeline pipelinewise init --n ...

  9. python 启动pydoc查看文档

    启动pydoc查看文档 python3 -m pydoc -p 访问http://localhost:6789 或者查看官方文档:https://seleniumhq.github.io/seleni ...

  10. 推荐 11 个好用的 JS 动画库

    为了保证的可读性,本文采用意译而非直译. 1.Three.js 超过46K的星星,这个流行的库提供了非常多的3D显示功能,以一种直观的方式使用 WebGL.这个库提供了<canvas>. ...