代码地址哦css
controller ——控制器层html
models ——数据层node
node_modules ——依赖包文件jquery
public ——静态文件目录git
uploads ——上传文件保存目录github
tempup ——临时缓存文件express
views ——显示层npm
app.js ——住文件入口json
package.json ——配置文件bootstrap
新建package.json文件,并执行npm install 安装依赖包文件,而后新建各个文件夹。
{ "name": "little-album", "version": "1.0.0", "description": "", "main": "app.js", "dependencies": { "ejs": "^2.3.4", "express": "^4.13.3", "formidable": "^1.0.17", "silly-datetime": "^0.1.2" }, "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
写入app.js,而且node app.js启动看看
// 引入express框架 var express = require('express'); // 注册express var app = express(); // 设置模板引擎ejs app.set('view engine', 'ejs'); // 设置静态资源路径 app.use(express.static("./public")); // 监听端口 app.listen(3004, function() { console.log("启动3004端口成功"); });
向app.js里面添加
// 引入控制器 var router = require('./controller'); // 设置路由 // --首页 app.get('/', router.showIndex);
router.showIndex是渲染控制器方法
向controller文件夹下添加router.js文件,且设置配置文件,package.json 设置默认入口为router.js不然默认index.js
{ "main": "router.js" }
// 设置首页模板渲染方法 exports.showIndex = function(req,res,next) { }
这里须要去文件夹拿照片 因此去models文件夹下新增file.js
新建file.js,写入查找文件的遍历方法
// 引入fs模块 var fs = require('fs'); // callback(err,date); // 找到uploads下全部文件夹 exports.getAllAlbums = function(callback) { // 读取文件夹内全部文件夹名字 fs.readdir('./uploads', function(err, files) { // 设置报错 if (err) { callback('没有找到uploads文件', null); } // 接收文件夹 var allAlbums = []; // 自执行遍历查询全部文件 (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); } // 加入数组 if (stats.isFile()) { allImages.push(files[i]); } // 下一次遍历 iterator(i + 1); }); })(0); }); }
修改router文件,
// 引入models var file = require('../models/file.js'); // 设置首页模板渲染方法 exports.showIndex = function(req, res, next) { // 找到upload下面全部文件夹名 file.getAllAlbums(function(err, allAlabums) { if (err) { // 交给下面的中间件 next(); return; } // 渲染模板,引用views里index模板 res.render('index', { 'albums': allAlabums }); }); }
而且在views文件夹下新增index.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 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>
在public文件夹下加入images文件夹且引入wjj.jpg图片文件
==在uploads下面新建几个文件夹 node app.js 运行看一下效果吧==
// --首页点击相册内页 app.get('/:albumName',router.showAlbum);
// 相册页 exports.showAlbum = function(req, res, next) { // 从url上拿到albumName字段 var albumName = req.params.albumName; // 交给models处理拿到images名字列表 file.getAllImagesByAlbumName(albumName, function(err, imagesArray) { if (err) { next(); return; } // 渲染album模板 res.render('album', { 'albumname' : albumName, 'images' : imagesArray }); }); }
<!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>
// 让存图片的文件夹也能访问 app.use(express.static('./uploads'));
==node app.js跑一下看下吧==
// --上传页面路由,接收页 app.get('/up', router.showUp);
// 上传接收页 exports.showUp = function(req, res, next) { // 获取全部文件夹名称 file.getAllAlbums(function(err, albums) { // 渲染up页面 res.render('up', { albums: albums }); }); }
这里循环拿到的文件夹名称数组albums
form提交 enctype="multipart/form-data" 要改为这个
<!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"> </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="#">上传</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container"> <div class="row"> <!-- form 必须改成multipart/form-data 才能拿到文件 --> <form style="width:40%;" method="post" action="#" enctype="multipart/form-data"> <div class="form-group"> <label for="exampleInputEmail1">选择文件夹</label> <!-- 循环拿到的albums文件夹名数组 --> <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> <p>尺寸小于2M</p> <input type="file" id="exampleInputFile" name="tupian"> </div> <button type="submit" class="btn btn-default">上传</button> </form> </div> </div> <script src="/js/jquery-1.11.3.min.js"></script> <script src="/js/bootstrap.min.js"></script> </body> </html>
ok啦 访问 /up 看下吧 ~
// --接收上传文件 app.post('/up', router.doPost);
向router里面添加方法
var fs = require('fs'); var sd = require('silly-datetime'); var path = require('path'); // 上传表单 exports.doPost = function(req, res, next) { // 使用 formidable 处理form 提交表单 var form = new formidable.IncomingForm(); // 设置临时文件上传路径 form.uploadDir = path.normalize(__dirname + '/../tempup'); // 解析请求中的表单数据 form.parse(req, function(err, fields, files, next) { console.log(fields); console.log(files); if (err) { // 抛给下一个 next(); return; } // 尺寸过大删除 // tupian 是html里面name设置的 var size = parseInt(files.tupian.size); if (size > 2000) { res.send('图片尺寸应该小鱼1M'); // 删除缓存图片 这里要用到fs模块 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; }
==运行下上传个图片看看效果吧==