MVC
- 指的是:models views controller;
- models:用于后臺(tái)數(shù)據(jù)的查找幔戏;
- views:視圖,用于存儲(chǔ)瀏覽器頁(yè)面的文件税课;
- controller:管理者闲延,控制者;用于二者之間的控制韩玩;
myAlbum項(xiàng)目開(kāi)發(fā)
- 創(chuàng)建文件夾:命令:mkdir
- models:提供數(shù)據(jù)垒玲;
- views:模板文件;
- controller:控制器找颓;
- uploads:上傳的文件
- public:靜態(tài)資源
- 創(chuàng)建文件:命令:touch ; window命令行中使用
type nul>
- app.js:入口文件合愈,創(chuàng)建服務(wù)器;
- package.json文件:記錄當(dāng)前項(xiàng)目依賴(lài)击狮;命令
npm init -y
; - 安裝項(xiàng)目模塊框架:命令
npm install --save-dev express ejs formidable
- controller文件夾下創(chuàng)建router.js文件佛析;作為一個(gè)路由的控制器;
- 知識(shí)點(diǎn):在app.js中引入自定義模塊彪蓬,必須添加相對(duì)路徑寸莫;如:
const router=require("./controller/router")
; - 在router.js中設(shè)置代碼輸出參數(shù);
exports.showIndex=function (req, res) { res.render("index") };
- 在app.js中直接引入:router.showIndex獲取匿名函數(shù);
- 知識(shí)點(diǎn):在app.js中引入自定義模塊彪蓬,必須添加相對(duì)路徑寸莫;如:
- 靜態(tài)資源文件加載
- 設(shè)置靜態(tài)資源在public文件下:
app.use(express.static("./public"));
档冬;即相對(duì)路徑都在public目錄下膘茎; - 在ejs文件中,通過(guò)link引入css文件和通過(guò)script引入js文件酷誓;都會(huì)發(fā)送對(duì)應(yīng)的請(qǐng)求披坏;請(qǐng)求地址為href和src中的路徑地址;
- 在通過(guò)get請(qǐng)求盐数,打開(kāi)index.ejs文件后棒拂,會(huì)在頁(yè)面中繼續(xù)發(fā)送請(qǐng)求;頁(yè)面想要有css樣式和js動(dòng)效娘扩,必須保證css文件和js文件能夠正常引入着茸;如何在頁(yè)面中渲染打開(kāi)css文件壮锻;css的引入地址是很重要的;
- 代碼:
app.use(express.static("./public"));
中將靜態(tài)資源的目錄設(shè)置在public目錄下涮阔,即所引入的css文件和js文件必須在此目錄下添加相對(duì)路徑猜绣,然后找到文件才能打開(kāi); - 所以敬特,將css文件和js文件放在public文件夾下掰邢,在引入時(shí)添加相對(duì)路徑;如:
<link href="/css/bootstrap.css" rel="stylesheet">
和<script src="/js/bootstrap.js"></script>
伟阔;注意:css前斜杠最好添加上辣之,若不添加,會(huì)被拼接在地址的后面皱炉,會(huì)出錯(cuò)怀估,所以必須添加; - 在地址欄中輸入地址
localhost:8080/css/bootstrap.css
也可以打開(kāi)引入的css文件合搅;
- 設(shè)置靜態(tài)資源在public文件下:
- 靜態(tài)資源設(shè)置的含義
- 代碼:
app.use(express.static("./public"))
- 含義:在express中多搀,設(shè)置靜態(tài)資源的請(qǐng)求路徑為public目錄下;
- 驗(yàn)證:在地址欄中輸入
localhost:8080/index.html
地址灾部,指的含義是查找到public目錄下的index.html康铭,打開(kāi)并渲染到頁(yè)面上; - 在index.html文件中有l(wèi)ink引入的css文件赌髓;如:
<link href="/css/bootstrap.css">
从藤;其中l(wèi)ink的href會(huì)發(fā)送請(qǐng)求;相當(dāng)于在地址欄中輸入localhost:8080/css/bootstrap.css
地址锁蠕;即夷野,在public目錄下查找css文件夾下的bootstrap.css文件,打開(kāi)并渲染到頁(yè)面中匿沛; - 結(jié)論:
- 設(shè)置了靜態(tài)資源的路徑扫责;則在地址欄中尋找的文件都是在public目錄下查找,如果查找到逃呼,則渲染鳖孤,查找不到,則會(huì)查看其它的請(qǐng)求是否存在此地址抡笼;
- 打開(kāi)html或ejs文件中苏揣,通過(guò)link或script或img中的href或src等引入文件,都會(huì)向服務(wù)器發(fā)送請(qǐng)求推姻;會(huì)默認(rèn)在public目錄下查找平匈;
- 代碼:
- 簡(jiǎn)單的實(shí)現(xiàn)index.ejs文件的頁(yè)面打開(kāi)渲染:
- index.ejs文件,通過(guò)設(shè)置get請(qǐng)求:
app.get("/",function(req,res){ res.render("index")};);
即:在地址欄中輸入"/",后可執(zhí)行匿名函數(shù)增炭;在匿名函數(shù)中通過(guò)res.render來(lái)默認(rèn)打開(kāi)views目錄下的index.ejs文件忍燥; - 打開(kāi)index.ejs文件后,里面引入的href和src再次發(fā)送多個(gè)請(qǐng)求隙姿;在設(shè)置的靜態(tài)資源目錄public文件夾下查找文件梅垄;然后打開(kāi)渲染;
- 代碼:
- index.ejs文件代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>模板</title> <link href="css/bootstrap.css" rel="stylesheet"> </head> <body> <h1>你好输玷,世界队丝!</h1> <script src="js/jquery.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
- app.js服務(wù)器代碼:
const express=require("express"); const app=express(); const router=require("./controller/router");//引入自定義模塊,必須添加相對(duì)路徑欲鹏; app.listen(8080); //發(fā)送請(qǐng)求机久,靜態(tài)渲染頁(yè)面 app.use(express.static("./public")); //設(shè)置模板引擎 app.set("view engine","ejs"); //通過(guò)"/"來(lái)發(fā)送請(qǐng)求,打開(kāi)views下的index.ejs文件 app.get("/",router.showIndex);
- router.js管理器代碼:
exports.showIndex=function (req, res) { res.render("index") };
- index.ejs文件,通過(guò)設(shè)置get請(qǐng)求:
項(xiàng)目開(kāi)發(fā)
- 搭建靜態(tài)頁(yè)面index.ejs赔嚎;利用bootstrap模板來(lái)創(chuàng)建頁(yè)面布局膘盖;
- 頁(yè)面中相冊(cè)的個(gè)數(shù)取決于uploads目錄下文件夾的個(gè)數(shù);
- 在頁(yè)面中利用ejs模板創(chuàng)建for循環(huán)尽狠,在服務(wù)器中通過(guò)render()傳送參數(shù)衔憨;即在router.js管理器中獲取參數(shù);router.js再去models中獲取數(shù)據(jù)袄膏;然后最終傳送給views中ejs頁(yè)面;
- 獲取磁盤(pán)中uploads目錄下文件夾的個(gè)數(shù)掺冠;
- 在models中files.js中獲取數(shù)據(jù)沉馆,導(dǎo)出數(shù)據(jù);利用fs文件系統(tǒng)中的readdir()來(lái)獲取文件夾下所有的文件德崭,再通過(guò)fs.stat()獲取每個(gè)文件的狀態(tài)stats斥黑,判斷stats.isDirectory()是否為true;如果文件是文件夾,則返回true;
- 通過(guò)自執(zhí)行函數(shù)和遞歸函數(shù)眉厨,將異步強(qiáng)制變成同步锌奴;然后待遍歷完,輸出數(shù)組憾股;
- 在匿名函數(shù)中如何輸出文件:通過(guò)callback參數(shù)鹿蜀;注意傳出的數(shù)據(jù)包括err錯(cuò)誤信息;
- 在router.js中引入自定義模塊files.js服球,添加相對(duì)路徑茴恰;通過(guò)匿名函數(shù)中的參數(shù)拿到文件夾信息;然后通過(guò)res.render()傳送給ejs文件使用斩熊;
- 注意點(diǎn):
- 在使用fs.readdir(path,()=>{})時(shí)往枣,path路徑為"./uploads",其中"./"拿到的是根目錄;不是"../"拿到根目錄分冈;
- 數(shù)據(jù)的輸出通過(guò)回調(diào)函數(shù)圾另,將異步操作中的結(jié)果輸出,但要注意輸出不同時(shí)刻的err信息雕沉;在成功輸出數(shù)據(jù)時(shí)盯捌,賦值為null,這樣在if(err)條件語(yǔ)句中蘑秽,就不會(huì)走語(yǔ)句饺著;
- 代碼:
- ejs代碼:
<div class="container"> <div class="row"> <% for(var i=0; i<albums.length; i++){%> <div class="col-xs-6 col-md-3"> <a href="/" class="thumbnail"> <img src="/img/01.jpg" alt="文件夾圖片"> </a> <h5 style="text-align: center;"><%= albums[i]%></h5> </div> <% }%> </div> </div>
- app.js代碼:
app.get("/",router.showIndex);
- router.js代碼:
//引入models中的files.js模塊; const modFiles=require("../models/files"); //顯示首頁(yè) exports.showIndex=function (req, res) { modFiles.showAllAlbums(function(err,albums){ if(err){ res.send(err); return;//阻斷程序執(zhí)行肠牲; } res.render("index",{ albums }) }); };
- files.js代碼:
//用于生產(chǎn)數(shù)據(jù)幼衰,然后輸給router.js使用; const fs=require("fs"); exports.showAllAlbums=function (callback) {//數(shù)據(jù)以回調(diào)函數(shù)的形式輸出缀雳; fs.readdir("./uploads",(err,files)=>{//地址為根目錄下的地址渡嚣; if(err){ callback(err,null); return; } var ary=[]; //把異步操作強(qiáng)制變成了同步操作; (function interator(i){ if(i>=files.length){ callback(null,ary);//null代表不會(huì)走if(err)條件肥印; return;//阻斷程序執(zhí)行识椰; } fs.stat("./uploads/"+files[i],(err,stats)=>{ if(err){ callback(err,null); return; } if(stats.isDirectory()){ ary.push(files[i]); } interator(++i); }) })(0); }); };
- 點(diǎn)擊文件夾后發(fā)送請(qǐng)求,打開(kāi)文件夾下的所有文件深碱;
- 發(fā)送請(qǐng)求:在地址欄中輸入文件夾名字后腹鹉,即發(fā)送了get請(qǐng)求,使其獲的數(shù)據(jù)并打開(kāi)渲染敷硅;在index.ejs中每一個(gè)文件夾都在一個(gè)a標(biāo)簽中功咒,設(shè)置href為
<a href="/<%= albums[i]%>" class="thumbnail">
,即根據(jù)文件夾的名字不同绞蹦,發(fā)送不同的請(qǐng)求力奋;跟地址欄中輸入localhost:8080/大學(xué)
是一樣的效果;從而實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn)幽七; - 打開(kāi)頁(yè)面景殷;需要新建一個(gè)showImg.ejs文件,里面是新的內(nèi)容澡屡;在發(fā)送
/:albumsImg
請(qǐng)求后猿挚,在files.js中打開(kāi)該文件夾,獲取文件夾下所有的文件挪蹭,通過(guò)fs.isFile()篩選出不是文件夾的文件亭饵;通過(guò)匿名函數(shù)傳出;然后渲染到頁(yè)面上梁厉,展示出相應(yīng)個(gè)數(shù)和名字的圖集辜羊; - 在頁(yè)面渲染中打開(kāi)img圖片踏兜;在files.js中只能拿到文件夾下的文件個(gè)數(shù)和文件名稱(chēng);無(wú)法打開(kāi)渲染八秃;res.render的作用是碱妆,打開(kāi)showImg.ejs文件,并且給其傳數(shù)據(jù)昔驱;只能渲染頁(yè)面疹尾,不能打開(kāi)img圖片;
- 呈現(xiàn)img圖片在頁(yè)面中骤肛,需要img標(biāo)簽中的src再次發(fā)送強(qiáng)求纳本,服務(wù)器接受進(jìn)行響應(yīng);所以腋颠,需要再設(shè)置靜態(tài)資源到
./uploads
目錄下繁成,指的是,發(fā)送來(lái)的請(qǐng)求閑雜public目錄下找文件淑玫,如果找不到巾腕,就到uploads目錄下查找,找到文件絮蒿,渲染打開(kāi)文件尊搬; - 注意1:img中src的路徑需要注意;當(dāng)showImg.ejs被渲染到頁(yè)面上的時(shí)候土涝,src才開(kāi)始發(fā)送請(qǐng)求佛寿;包括css和js也會(huì)發(fā)送請(qǐng)求;
- img的src設(shè)置時(shí)有兩種方式回铛;1)
<img src="/<%= albumsImg%>/<%= albums[i]%>" alt="文件夾圖片">
狗准,在地址中添加文件夾路徑;2)<img src="<%= albums[i]%>" alt="文件夾圖片">
茵肃,在地址中不添加文件夾路徑但是不能添加"/",可能的原因是在地址欄中已經(jīng)存在http://localhost:8080/大學(xué)/
; - css和js文件src中必須添加"/"袭祟,不能省略验残;
- img的src設(shè)置時(shí)有兩種方式回铛;1)
- 注意2:使用req.params.albumsImg獲取請(qǐng)求地址時(shí),除了文件夾地址巾乳,還會(huì)得到favicon.ico您没,所以需要在獲取文件夾下文件的函數(shù)中,阻止favicon.ico運(yùn)行胆绊;
- 代碼:
- showImg.ejs代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>展示圖片</title> <link href="/css/bootstrap.css" rel="stylesheet"> </head> <body> <% include include/header.ejs%> <section class="container"> <ol class="breadcrumb"> <li><a href="/">全部相冊(cè)</a></li> <li class="active"><%= albumsImg%></li> </ol> </section> <div class="container"> <div class="row"> <% for(var i=0; i<albums.length; i++){%> <div class="col-xs-6 col-md-3"> <span class="thumbnail"> <img src="/<%= albumsImg%>/<%= albums[i]%>" alt="文件夾圖片"> </span> <h5 style="text-align: center;"><%= albumsName[i]%></h5> </div> <% }%> </div> </div> <script src="/js/jquery.js"></script> <script src="/js/bootstrap.js"></script> </body> </html>
- app.js代碼:
const express=require("express"); const app=express(); const router=require("./controller");//引入自定義模塊氨鹏,必須添加相對(duì)路徑;因?yàn)閏ontroller創(chuàng)建了package.json文件压状,在里面設(shè)置了main屬性仆抵,設(shè)置默認(rèn)的入口文件為router.js文件跟继; app.listen(8080); //發(fā)送請(qǐng)求,靜態(tài)渲染頁(yè)面 //1.設(shè)置靜態(tài)資源路徑在public目錄下镣丑,用于渲染引入的css文件和js文件舔糖; app.use(express.static("./public")); //2.設(shè)置靜態(tài)資源路徑在uploads目錄下,用于渲染img圖片莺匠; app.use(express.static("./uploads")); //設(shè)置模板引擎 app.set("view engine","ejs"); //通過(guò)"/"來(lái)發(fā)送請(qǐng)求金吗,打開(kāi)views下的index.ejs文件 app.get("/",router.showIndex); //發(fā)送get請(qǐng)求:地址:"/大學(xué)",打開(kāi)views下的showImg.ejs文件趣竣; app.get("/:albumsImg",router.showImg);
- router.js代碼:
//顯示相冊(cè)文件夾中的圖片 exports.showImg=function (req, res) { var albumsImg=req.params.albumsImg; modFiles.showAlbumsImgs(albumsImg,function (err,albums,albumsName) { //如果有錯(cuò)誤摇庙,則顯示在頁(yè)面上,并阻斷程序執(zhí)行遥缕; if(err){ res.send(err);//send后面可以寫(xiě)return; return;//必須阻斷程序執(zhí)行卫袒; } res.render("showImg",{ albumsImg, albums, albumsName }) }); };
- files.js代碼:
//獲取地址欄中發(fā)送的地址文件夾下的所有圖片文件;生成數(shù)組導(dǎo)出通砍; exports.showAlbumsImgs=function (albumsImg, callback) { //albumsImg是地址欄中的文件夾名稱(chēng)玛臂;callback用來(lái)導(dǎo)出數(shù)據(jù); //讀取文件夾下的文件 fs.readdir("./uploads/"+albumsImg,function (err, files) { if(err){ callback("讀取文件夾失敗",null,null); return; } var albums=[]; var albumsName=[]; (function interator(i) { if(i>=files.length){ callback(null,albums,albumsName); return; } fs.stat("./uploads/"+albumsImg+"/"+files[i],function (err, stats) { if(err){ callback("讀取文件夾下的文件失敗",null,null); return; } if(stats.isFile()){ //成立封孙,則證明不是文件夾 albums.push(files[i]); albumsName.push(path.parse(files[i]).name); } interator(++i); }) })(0); }) };
- 發(fā)送請(qǐng)求:在地址欄中輸入文件夾名字后腹鹉,即發(fā)送了get請(qǐng)求,使其獲的數(shù)據(jù)并打開(kāi)渲染敷硅;在index.ejs中每一個(gè)文件夾都在一個(gè)a標(biāo)簽中功咒,設(shè)置href為
- 頁(yè)面的操作:
- 提煉出兩個(gè)ejs頁(yè)面中的公共的代碼迹冤,放在views下的include文件夾下的header.ejs文件中;這樣在文件中引入此文件即可虎忌;
- 優(yōu)點(diǎn):當(dāng)頁(yè)面公共部分的代碼泡徙,發(fā)生變化,只需在header.ejs文件中修改即可膜蠢,否則堪藐,還需分別再兩個(gè)文件中修改;
- 引入include.ejs文件代碼:
<% include include/header.ejs%>
挑围,其中include/header.ejs
為相對(duì)路徑礁竞,無(wú)需加引號(hào);
- 圖片上傳功能
- 思路:
- 創(chuàng)建form.ejs表單頁(yè)面杉辙;通過(guò)form表單來(lái)提交數(shù)據(jù)模捂;
- 發(fā)送get請(qǐng)求,通過(guò)header.ejs中的上傳a標(biāo)簽href設(shè)置地址蜘矢,點(diǎn)擊發(fā)送請(qǐng)求狂男;打開(kāi)form.ejs頁(yè)面;傳送數(shù)據(jù)品腹;用于select表單中獲取文件夾數(shù)據(jù)岖食;
- 發(fā)送post請(qǐng)求,通過(guò)表單中submit提交按鈕舞吭,設(shè)置form中的action和method泡垃;點(diǎn)擊發(fā)送post請(qǐng)求析珊;
- 在router.js中通過(guò)formidable模塊來(lái)獲取上傳的數(shù)據(jù);
- 新建form對(duì)象兔毙;
var form= new formidable.IncomingForm()
唾琼; - 設(shè)置上傳地址;
form.uploadDir="./uploads/"
澎剥; - 通過(guò)form.parse()拿數(shù)據(jù)锡溯;=》fields:表單上傳參數(shù)組成的對(duì)象;files:表單file中name組成的對(duì)象哑姚;用于獲取上傳圖片的路徑名字祭饭;以及上傳之前的名字;
- 通過(guò)
files.tupian.size
叙量,拿到上傳文件的大小倡蝙,然后進(jìn)行判斷,如果大于某值绞佩,則用fs.unlink()
刪除已經(jīng)上傳的文件寺鸥;注意,在條件判斷中設(shè)置return品山;阻斷程序向下運(yùn)行胆建; - 通過(guò)fs.rename()將oldpath改為newpath,修改原來(lái)文件名字并移動(dòng)該文件到新的路徑下肘交;
- 新建form對(duì)象兔毙;
- 修改成功后笆载,打開(kāi)對(duì)應(yīng)文件夾的圖集;調(diào)用
modFiles.showAlbumsImgs(albumsImg,function (err,albums,albumsName){})
涯呻; - 修改成功后凉驻,可以通過(guò)
res.redirect("/中學(xué)")
來(lái)進(jìn)行重定向頁(yè)面跳轉(zhuǎn);
- 注意點(diǎn):
- 設(shè)置get請(qǐng)求"/upload"時(shí)复罐,必須放在
app.get("/:albumsImg",router.showImg);
前面涝登,否則,不會(huì)走該請(qǐng)求效诅;必須將嚴(yán)格的請(qǐng)求放在不嚴(yán)格的請(qǐng)求的前面缀拭; - form表單中,seclect和file必須設(shè)置name值填帽,否則無(wú)法獲取數(shù)據(jù);seclect的name值用來(lái)獲取放在哪個(gè)文件夾下咙好,file的name值是用來(lái)作為files對(duì)象中屬性名來(lái)獲取上傳文件的數(shù)據(jù)的篡腌;
- form表單中的action設(shè)置請(qǐng)求地址,method設(shè)置post請(qǐng)求勾效,enctype設(shè)置大文件下的類(lèi)型嘹悼;
- 利用formidable模塊獲取files對(duì)象后叛甫,path屬性拿到的是路徑加文件名;作為oldpath杨伙;newpath包含相對(duì)路徑和文件名其监;相對(duì)路徑設(shè)置為uploads下的對(duì)應(yīng)文件夾中;
- 在修改名字后限匣,原來(lái)上傳的文件會(huì)被移動(dòng)到新的路徑下抖苦;
- 在設(shè)置上傳地址時(shí)地址后面必須加"/",否則米死,無(wú)法使用锌历;如
form.uploadDir="./uploads/";
- 注意異步和同步問(wèn)題;
- 設(shè)置get請(qǐng)求"/upload"時(shí)复罐,必須放在
- 代碼:
- form-upload.ejs代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>表單上傳文件</title> <link href="/css/bootstrap.css" rel="stylesheet"> </head> <body> <% include include/header.ejs%> <section class="container"> <form action="/doupload" method="post" enctype="multipart/form-data"> <div class="form-group"> <label for="wenjian">相冊(cè)目錄</label> <select class="form-control" name="wenjianjia" id="wenjian"> <% for(var i=0; i<albums.length; i++){%> <option><%= albums[i]%></option> <%}%> </select> </div> <div class="form-group"> <label for="InputFile">上傳文件路徑</label> <input type="file" id="InputFile" name="tupian"> </div> <button type="submit" class="btn btn-primary">上傳</button> </form> </section> <script src="/js/jquery.js"></script> <script src="/js/bootstrap.js"></script> </body> </html>
- app.js代碼:
/發(fā)送get請(qǐng)求:地址:"/upload",打開(kāi)views下的form.ejs文件峦筒; app.get("/upload",router.upload); //發(fā)送post請(qǐng)求究西,地址:"/doupload",上傳文件物喷; app.post("/doupload",router.doUpload); //以上代碼必須放在下面代碼前面卤材; //發(fā)送get請(qǐng)求:地址:"/大學(xué)",打開(kāi)views下的showImg.ejs文件峦失; app.get("/:albumsImg",router.showImg);
- router.js代碼:
//上傳文件獲取數(shù)據(jù) exports.doUpload=function (req, res) { //新建一個(gè)form對(duì)象 var form= new formidable.IncomingForm(); //設(shè)置上傳地址 form.uploadDir="./uploads/"; //解析文件 form.parse(req,(err,fields,files)=>{ //修改文件名扇丛,放在指定文件夾下 var oldpath=files.tupian.path; var newpath=form.uploadDir+fields.wenjianjia+"/"+files.tupian.name; fs.rename(oldpath,newpath,function (err) { if(err){ res.send("修改名字失敗"); return; }else{ //res.send("上傳成功");//注意異步問(wèn)題;所以此代碼不能寫(xiě)在外面宠进; //當(dāng)上傳成功后晕拆,跳轉(zhuǎn)到相應(yīng)的文件夾中打開(kāi); var albumsImg=fields.wenjianjia; modFiles.showAlbumsImgs(albumsImg,function (err,albums,albumsName) { //如果有錯(cuò)誤材蹬,則顯示在頁(yè)面上实幕,并阻斷程序執(zhí)行; if(err){ res.send(err);//send后面可以寫(xiě)return; return;//必須阻斷程序執(zhí)行堤器; } res.render("showImg",{ albumsImg, albums, albumsName }) }); } }) }); };
- 思路:
- 接盤(pán)俠
- 在最后設(shè)置use請(qǐng)求昆庇,請(qǐng)求地址為"/",即所有的地址都可以進(jìn)入請(qǐng)求闸溃;渲染打開(kāi)404.ejs文件整吆,顯示404頁(yè)面;
- 代碼:
//設(shè)置404頁(yè)面辉川,用來(lái)接底 app.use("/",function (req, res) { res.render("404");//打開(kāi)404.ejs文件表蝙; });
- 利用middleware中間件來(lái)設(shè)置錯(cuò)誤流,當(dāng)進(jìn)入一個(gè)請(qǐng)求后乓旗,如果出現(xiàn)err府蛇,則通過(guò)next(),來(lái)向下接著請(qǐng)求屿愚,最終到達(dá)use請(qǐng)求汇跨,渲染404頁(yè)面务荆;
- 在router.js文件中所有請(qǐng)求的匿名函數(shù);均要設(shè)置next,當(dāng)err情況下穷遂,設(shè)置next(),并阻斷程序執(zhí)行函匕;
- files.js文件中err不需要設(shè)置next(),因?yàn)橥ㄟ^(guò)callback已經(jīng)將err返回到router.js中;
- 這樣設(shè)置蚪黑,也可以解決地址具體地址和廣泛地址的影響盅惜;
- 注意:send()后面不能設(shè)置任何東西;可以寫(xiě)return;
項(xiàng)目開(kāi)發(fā)中的架構(gòu)格局
- 文件分類(lèi)及作用
- MVC結(jié)構(gòu):
- M:models:用來(lái)獲取后臺(tái)的數(shù)據(jù)庫(kù)祠锣,通過(guò)exports輸出給controller管理器酷窥;
- 創(chuàng)建files.js文件,作為后臺(tái)數(shù)據(jù)的模塊伴网;通過(guò)exports來(lái)傳出數(shù)據(jù)蓬推,在router.js管理器中引入此模塊,用于獲取傳出數(shù)據(jù)澡腾;
- V:views: 目錄下存在ejs文件沸伏,作為瀏覽器視圖的渲染文件;
- 存儲(chǔ)ejs文件动分,用于頁(yè)面的打開(kāi)渲染毅糟;
- 創(chuàng)建include文件夾,里面創(chuàng)建header.ejs文件澜公,作為ejs文件的公共部分代碼姆另;通過(guò)
<% include include/header.ejs%>
引入到其他文件中;
- C:controller:管理器坟乾;用來(lái)連接models和views迹辐;
- 作用:作為一個(gè)管理者,在views中通過(guò)render來(lái)打開(kāi)ejs文件甚侣,在數(shù)據(jù)庫(kù)或models中拿數(shù)據(jù)明吩;
- 創(chuàng)建router.js文件,作為數(shù)據(jù)的管理器殷费;通過(guò)exports來(lái)傳出數(shù)據(jù)印荔;在app.js中引入此模塊來(lái)獲取數(shù)據(jù);
- 創(chuàng)建package.json文件详羡,通過(guò)設(shè)置里面的main屬性仍律,來(lái)設(shè)置默認(rèn)入口文件router.js;則在app.js服務(wù)器文件中引入模塊時(shí)实柠,可以直接引入controller文件夾染苛,如
const router=require("./controller")
;
- 三者之間的關(guān)系:
- 當(dāng)服務(wù)器中接受到瀏覽器發(fā)送的請(qǐng)求后,向controller管理器請(qǐng)求;如代碼:
app.get("/",router.showIndex);
茶行;router.js中設(shè)置匿名函數(shù);渲染頁(yè)面登钥; - 當(dāng)瀏覽器中需要uploads文件夾下的文件夾個(gè)數(shù)時(shí)畔师,向controller管理器要數(shù)據(jù);controller再向models后臺(tái)數(shù)據(jù)庫(kù)中查找獲饶晾巍看锉;models數(shù)據(jù)也通過(guò)exports輸出數(shù)據(jù);
- 當(dāng)服務(wù)器中接受到瀏覽器發(fā)送的請(qǐng)求后,向controller管理器請(qǐng)求;如代碼:
- M:models:用來(lái)獲取后臺(tái)的數(shù)據(jù)庫(kù)祠锣,通過(guò)exports輸出給controller管理器酷窥;
- public文件夾:用于存儲(chǔ)靜態(tài)文件塔鳍;如css,js文件伯铣;通過(guò)在服務(wù)器中設(shè)置靜態(tài)渲染來(lái)引用文件;
- app.js:為入口文件轮纫,用于創(chuàng)建服務(wù)器來(lái)前后臺(tái)交互腔寡;
- package.json:用于記錄項(xiàng)目依賴(lài)的文件;
- readme.md:讀者讀的文檔掌唾,用于解讀項(xiàng)目放前;
- MVC結(jié)構(gòu):
- 請(qǐng)求及目的
- get請(qǐng)求,是為了渲染打開(kāi)頁(yè)面糯彬;
- get-"/"=>打開(kāi)index.ejs;即凭语,打開(kāi)圖片首頁(yè),根據(jù)uploads下文件夾的個(gè)數(shù)撩扒,呈現(xiàn)出相應(yīng)個(gè)數(shù)的圖集似扔;
- get-"/:albumsImg" => 打開(kāi)showImg.ejs;即呈現(xiàn)出每個(gè)albumsImg文件夾下的圖片搓谆;
- get-"/upload" => 打開(kāi)form上傳文件表單炒辉;用于上傳圖片文件;
- post請(qǐng)求挽拔,是真正做一些功能的辆脸,如上傳文件;
- post-"/doupload" => 通過(guò)表單中的submit提交按鈕螃诅,來(lái)發(fā)送post請(qǐng)求啡氢,進(jìn)行圖片文件的上傳;
- use請(qǐng)求:請(qǐng)求地址設(shè)置為"/"术裸,可以省略倘是,作為接盤(pán)俠;
- use-"/" => 打開(kāi)404.ejs文件袭艺,呈現(xiàn)404頁(yè)面搀崭,配合middleware中間件使用;
- get請(qǐng)求,是為了渲染打開(kāi)頁(yè)面糯彬;
項(xiàng)目開(kāi)發(fā)中的知識(shí)點(diǎn)
- 在controller文件夾中創(chuàng)建package.json文件,里面設(shè)置main屬性瘤睹,來(lái)設(shè)置默認(rèn)的入口文件為router.js升敲,這樣在app.js服務(wù)器中引入模塊時(shí),只引入文件夾controller轰传;即:
const router=require("./controller")
; - 在項(xiàng)目開(kāi)發(fā)中如果匿名函數(shù)中存在err錯(cuò)誤代碼驴党,必須設(shè)置相應(yīng)的條件語(yǔ)句,然后傳出錯(cuò)誤信息获茬;后面一定要加return港庄,阻斷程序執(zhí)行;
- 使用req.params.albumsImg獲取請(qǐng)求地址時(shí)恕曲,除了文件夾地址鹏氧,還會(huì)得到favicon.ico,所以需要在獲取文件夾下文件的函數(shù)中佩谣,阻止favicon.ico運(yùn)行把还;
- 1M等于1024K,1K等于1024字節(jié),文件上傳時(shí)稿存,通過(guò)
files.tupian.size
來(lái)獲取上傳文件的大小笨篷,單位為字節(jié); - 接盤(pán)use請(qǐng)求和middleware的設(shè)置
- use請(qǐng)求地址為"/"瓣履,可以省略率翅;當(dāng)所有請(qǐng)求都不成立的時(shí)候,最后請(qǐng)求use的匿名函數(shù)袖迎,打開(kāi)404頁(yè)面文件冕臭;
- 前提是在每個(gè)請(qǐng)求的匿名函數(shù)中設(shè)置middleware中間件;即next();當(dāng)err時(shí)設(shè)置next(),并阻斷程序執(zhí)行燕锥;