簡介
Express 是基於 Node.js 平台,快速、開放、極簡的 Web 開發框架, 提供一系列強大特性幫助你創建各種Web應用。Express 不對 node.js 已有的特性進行二次抽象,我們只是在它之上擴展了Web應用所需的功能。豐富的HTTP工具以及來自Connect框架的中間件隨取隨用,創建強健、友好的API變得快速又簡單
官網
安裝
首先假定你已經安裝了 Node.js,接下來為你的應用創建一個目錄,然后進入此目錄並將其作為當前工作目錄。
通過 npm init
命令為你的應用創建一個 package.json
文件。 欲了解 package.json
是如何起作用的,請參考 Specifics of npm’s package.json handling.
$ npm init
此命令將要求你輸入幾個參數,例如此應用的名稱和版本。 你可以直接按“回車”鍵接受大部分默認設置即可,下面這個除外:
entry point: (index.js)
鍵入 app.js
或者你所希望的名稱,這是當前應用的入口文件。如果你希望采用默認的 index.js
文件名,只需按“回車”鍵即可。
接下來在 myapp
目錄下安裝 Express 並將其保存到依賴列表中。如下:
$ npm install express --save
如果只是臨時安裝 Express,不想將它添加到依賴列表中,可執行如下命令:
$ npm install express --no-save
npm 5.0+ 版本在默認情況下會將安裝的模塊添加到 package.json
文件中的 dependencies
列表中。對於較老的 npm 版本,你就必須指定 --save
參數。然后,照舊執行 npm install
命令即可自動安裝依賴列表中所列出的所有模塊。
hello world
創建app.js 並寫入
const express = require('express');
const app = express();
const port = 3000;
app.get('/', function(req, res) {
res.send('Hello World!')
});
app.listen(port, function(){
console.log(`請求訪問127.0.0.1:${port}!`)
});
運行結果
到此簡單的hello world 已經完成
使用
內置路由和外置路由
內置路由和外置路由簡單理解就是把路由寫在app.js(入口文件)文件中,還是寫在其他文件中,寫在app.js文件里就是內置路由其他文件就是外置路由。如上面的hello world案例就是內置路由,不過一般都是使用外置路由。
例
route.js
//引入express 框架模塊
var express = require('express');
//獲取路由對象
var router = express.Router();
//設置路由
router.get('/',(req,res)=>{
res.send('123');
})
router.get('/user',(req,res)=>{
res.send('user');
})
router.post('/edit',(req,res)=>{
res.send('post_edit');
})
// 導出 路由router
module.exports = router;
app.js
var express = require('express');
var app = express();
// 引入外置路由模塊
var rout = require('./route');
// 使用引入外置的路由
app.use(rout);
app.listen('8000',()=>{
console.log('127.0.0.1:8000')
})
運行結果
使用art-template模板引擎
在express框架中使用art-template模板引擎還需要安裝express-art-template
安裝
npm install --save art-template
npm install --save express-art-template
官方示例:
var express = require('express');
var app = express();
app.engine('art', require('express-art-template'));
app.set('view options', {
debug: process.env.NODE_ENV !== 'production'
});
app.get('/', function (req, res) {
res.render('index.art', {
user: {
name: 'aui',
tags: ['art', 'template', 'nodejs']
}
});
});
Demo
app.js
var express = require('express');
var app = express();
//注冊引擎
app.engine('html', require('express-art-template'));
// 引入外置路由模塊
var rout = require('./route');
// 使用引入外置的路由
app.use(rout);
app.listen('8000',()=>{
console.log('127.0.0.1:8000')
})
route.js
//引入express 框架模塊
var express = require('express');
//獲取路由對象
var router = express.Router();
//設置路由
router.get('/',(req,res)=>{
//默認會去當前目錄下的views目錄下獲取靜態頁面
res.render('index.html', {title:'express-art-template-title'});
})
// 導出 路由router
module.exports = router;
./views/index.html
<h1>{{title}}</h1>
運行結果
遇到的問題
模板路徑的問題
在項目中新建views目錄,將所有靜態頁面放入views目錄
響應html頁面
之前使用http模塊的時候,是用fs讀取html文件內容並且設置響應頭才可以響應html頁面,比較麻煩。那么現在express框架有什么比較簡單的辦法呢?
API
res.sendFile(路徑[,選項] [,fn])
res.sendFile()
Express v4.8.0及更高版本受支持。
在給定的位置傳輸文件path
。Content-Type
根據文件名的擴展名設置響應HTTP標頭字段。除非root
在選項對象中設置了選項,path
否則必須是文件的絕對路徑。
該API提供對正在運行的文件系統上的數據的訪問。確保(a)如果path
參數包含用戶輸入,則將參數構造為絕對路徑的方法是安全的;或者(b)將root
選項設置為包含訪問權限的目錄的絕對路徑。
當root
被提供的選項,所述path
參數被允許是相對路徑,包括含有..
。Express將驗證提供的相對路徑path
是否可以在給定的root
選項內解析。
下表提供了有關該options
參數的詳細信息。
屬性 | 描述 | 默認 | 可用性 |
---|---|---|---|
maxAge |
Cache-Control 以毫秒為單位設置標頭的max-age屬性,或以ms格式設置字符串 |
0 | |
root |
相對文件名的根目錄。 | ||
lastModified |
將Last-Modified 標頭設置為操作系統上文件的最后修改日期。設置false 為禁用它。 |
已啟用 | 4.9.0+ |
headers |
包含要與文件一起使用的HTTP標頭的對象。 | ||
dotfiles |
用於提供點文件的選項。可能的值為“允許”,“拒絕”,“忽略”。 | “忽視” | |
acceptRanges |
啟用或禁用接受遠程請求。 | true |
4.14+ |
cacheControl |
啟用或禁用設置Cache-Control 響應頭。 |
true |
4.14+ |
immutable |
immutable 在Cache-Control 響應頭中啟用或禁用指令。如果啟用,maxAge 還應指定該選項以啟用緩存。該immutable 指令將阻止受支持的客戶端在maxAge 選項的有效期內提出條件請求,以檢查文件是否已更改。 |
false |
4.16+ |
fn(err)
傳輸完成或發生錯誤時,該方法將調用回調函數。如果指定了回調函數並且發生錯誤,則回調函數必須通過結束請求-響應周期或將控制權傳遞給下一條路由來顯式處理響應過程。
注意:上面寫了除非設置了root選項,否則文件路徑必須是絕對路徑
這時候就要使用__dirname
這個,來獲取當前目錄的絕對路徑了
文檔:http://nodejs.cn/api/modules/dirname.html
響應html頁面的Demo
route.js
//引入express 框架模塊
var express = require('express');
//獲取路由對象
var router = express.Router();
//設置路由
router.get('/',(req,res)=>{
//只能絕對路徑
res.sendFile(__dirname+'/views/index.html');
})
// 導出 路由router
module.exports = router;
利用 Express 托管靜態文件
官方文檔:http://www.expressjs.com.cn/starter/static-files.html
為了提供諸如圖像、CSS 文件和 JavaScript 文件之類的靜態文件,請使用 Express 中的 express.static
內置中間件函數。
此函數特征如下:
express.static(root, [options])
The root
argument specifies the root directory from which to serve static assets. For more information on the options
argument, see express.static.
例如,通過如下代碼就可以將 public
目錄下的圖片、CSS 文件、JavaScript 文件對外開放訪問了:
app.use(express.static('public'))
現在,你就可以訪問 public
目錄中的所有文件了:
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
Express 在靜態目錄查找文件,因此,存放靜態文件的目錄名不會出現在 URL 中。
如果要使用多個靜態資源目錄,請多次調用 express.static
函數:
app.use(express.static('public'))
app.use(express.static('files'))
訪問靜態資源文件時,express.static
函數會根據目錄的添加順序查找所需的文件。
Demo
1.新建靜態資源存放路徑,如public
2.入口文件中設置靜態資源目錄
app.use(express.static('public'))
就可以了
例:
app.js
var express = require('express');
var app = express();
//設置靜態資源目錄
app.use(express.static('public'))
app.listen('8000',()=>{
console.log('127.0.0.1:8000')
})
./public/img/test.jpg
訪問http://127.0.0.1:8000/img/test.jpg
如果是在其他靜態頁面中使用則直接寫
<img src="/img/test.jpg">
直接寫相對於public 的目錄下的路徑即可
使用formidable進行文件上傳
npm地址:https://www.npmjs.com/package/formidable
安裝
npm install formidable
選項
options.encoding
{string} -默認值'utf-8'
;設置傳入表單字段的編碼,options.uploadDir
{string} -默認值os.tmpdir()
;用於放置文件上載的目錄。稍后可以使用進行移動fs.rename()
options.keepExtensions
{boolean} -默認值false
;是否包含原始文件的擴展名options.maxFileSize
{number} -默認值200 * 1024 * 1024
(200mb);限制上傳文件的大小。options.maxFields
{number} -默認值1000
;限制Querystring解析器將解碼的字段數,將0設置為無限制options.maxFieldsSize
{number} -默認值20 * 1024 * 1024
(20mb);限制所有字段(文件除外)可一起分配的內存量(以字節為單位)。options.hash
{boolean} -默認值false
;包括為傳入文件計算的校驗和,將其設置為某種哈希算法, 有關可用算法,請參見 crypto.createHashoptions.multiples
{boolean} -默認值false
;當您調用該.parse
方法時,files
(回調的)參數將包含用於輸入的文件數組,這些輸入使用HTML5multiple
屬性提交多個文件。同樣,該fields
參數將包含名稱以“ []”結尾的字段的值數組。
普通表單控件和文件表單控件數據結構示例
普通表單控件
{ name: 'zhangsan' }
文件表單控件
{
file: File {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
//文件大小
size: 57313,
//文件路徑
path: 'public\\upload_aa5dfaec37e92b4efe60ae1cec4d6f2d.jpg',
//文件名
name: 'u=313355857,739398057&fm=26&gp=0.jpg',
//文件類型
type: 'image/jpeg',
hash: null,
//最后修改時間
lastModifiedDate: 2020-10-06T09:17:13.572Z,
_writeStream: WriteStream {
_writableState: [WritableState],
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
path: 'public\\upload_aa5dfaec37e92b4efe60ae1cec4d6f2d.jpg',
fd: 3,
flags: 'w',
mode: 438,
start: undefined,
autoClose: true,
pos: undefined,
bytesWritten: 57313,
closed: false,
[Symbol(kFs)]: [Object],
[Symbol(kCapture)]: false,
[Symbol(kIsPerformingIO)]: false
},
[Symbol(kCapture)]: false
}
}
Demo
var express = require('express');
var fs = require('fs');
var formidable = require('formidable');
var app = express();
app.post('/upload',(req,res)=>{
//創建上傳表單
var form = new formidable.IncomingForm();
//設置
//formidable的默認保存路徑是:“C:\Users\Administrator\AppData\Local\Temp”
//修改formidable 臨時存放存儲路徑為當前目錄下的public
form.uploadDir = './public';
// 保留文件擴展名
form.keepExtensions = true;
/**
* err 表示錯誤信息
* fields 表示普通表單控件
* files 表示文件表單控件
*/
form.parse(req, function (err, fields, files) {
console.log(fields);
console.log(files);
var times = new Date().getTime();
// 組裝上傳路徑
var file_path = './public/'+times+files.file.name;
// 將緩存文件移動至制定目錄
fs.rename(files.file.path,file_path,(err)=>{
console.log(file_path);
});
res.end();
});
})
app.listen('8000',()=>{
console.log('127.0.0.1:8000')
})
運行結果
使用cookie與session
express官方資源中,為我們提供了一個中間件,cookie-session
安裝
npm install cookie-session
Demo
var express = require('express');
var cookieSession = require('cookie-session')
var app = express();
// 注冊中間件
app.use(cookieSession({
name: 'session', // 客戶端cookie的名稱
keys: ['ss'] // 用於加密的關鍵字
}))
app.get('/', (req, res) => {
// 獲取並判斷session
if(req.session.sess_data){
res.send('已經登陸')
}else{
// 如果沒有session,跳轉到登陸頁面
res.send('<script>alert("沒登陸");window.location.href="/up"</script>');
}
})
app.get('/up', (req, res) => {
// 展示登陸頁面,獲取用戶數據並寫入session
req.session.sess_data = {name:12,age:89};
res.send('已寫入session');
});
app.listen('8000',()=>{
console.log('127.0.0.1:8000')
})
這個Demo第一次訪問如果沒session 會在彈框之后自動寫入session
再次訪問
Express的中間件
什么是中間件
在一個整體的流程中的某個環節,因為某些原因加入了額外的處理環節;
中間件的使用
應用中間件
語法:
app.use()
app.use(function(){})
無論發送任何請求都會執行的中間件
app.use('/path', function(){})
只要在請求path路由時才會執行的中間件(無論GET/POST)
app.method()
app.get()
在get請求時會執行的中間件
app.post()
在post請求時會執行的中間件
app.use() 的用法
var express = require('express');
var app = express();
// 在中間件之前,不受中間件影響
app.get('/',function(req,res){
console.log(123);
})
// 應用中間件
//表示匹配任何路由
// 請求 '/user' 時,會先調用中間件
app.use(function (req, res, next) {
console.log(req);
next();
});
// 調用之前先調用中間件
app.get('/user',function(req,res){
console.log('user');
})
app.listen('8000', () => {
console.log('127.0.0.1:8000')
})
app.method() 的用法
var express = require('express');
var app = express();
// 在中間件之前,不受中間件影響
app.get('/',function(req,res){
console.log(123);
})
// 應用中間件,也叫路由中間件
// 只有在 post 請求user 時才起作用
app.post('/user',function (req, res, next) {
console.log(req);
//表示匹配完成這個中間件就繼續往下執行。
next();
});
// 調用之前先調用中間件
// 接受所有請求方式請求user
app.all('/user',function(req,res){
console.log('user');
})
app.listen('8000', () => {
console.log('127.0.0.1:8000')
})
路由中間件
路由器層中間件的工作方式與應用層中間件基本相同,差異之處在於它綁定到 express.Router()
的實例。
使用 router.use()
和 router.METHOD()
函數裝入路由器層中間件;
例:
var app = express();
var router = express.Router();
//沒有掛載路徑的中間件。這段代碼對每個發送到路由器的請求都執行
router.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
//中間件子堆棧向/user/:id路徑顯示任何類型的HTTP請求的請求信息
router.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// 處理/user/:id路徑的GET請求的中間件子堆棧
router.get('/user/:id', function (req, res, next) {
// 如果用戶ID為0,則跳到下一個路由器
if (req.params.id == 0) next('route');
// 否則,將控制權傳遞給該堆棧中的下一個中間件函數
else next(); //
}, function (req, res, next) {
// 呈現常規頁面
res.render('regular');
});
// 用於/user/:id路徑的處理程序,它將呈現一個特殊的頁面
router.get('/user/:id', function (req, res, next) {
console.log(req.params.id);
res.render('special');
});
// 使用路由
app.use('/', router);
內置中間件
除 express.static
外,先前 Express 隨附的所有中間件函數現在以單獨模塊的形式提供:中間件函數的列表
Express 中唯一內置的中間件函數是 express.static
。此函數基於 serve-static,負責提供 Express 應用程序的靜態資源。
對於每個應用程序,可以有多個靜態目錄:
app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));
第三方中間件
使用第三方中間件向 Express 應用程序添加功能。
安裝具有所需功能的 Node.js 模塊,然后在應用層或路由器層的應用程序中將其加裝入。
var cookieSession = require('cookie-session');
// 注冊中間件
app.use(cookieSession({
name: 'session', // 客戶端cookie的名稱
keys: ['xilingzuishuai'] // 用於加密的關鍵字
}))