※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。
一、文件系統
fs模塊可與文件系統進行交互,封裝了常規的POSIX函數。POSIX(Portable Operating System Interface,可移植操作系統接口)是UNIX系統的一個設計標準。fs模塊提供了多個操作目錄和文件的方法,大多會有同步和異步兩種版本,同步的方法名稱會以Sync為後綴。
1)目錄處理
fs模塊的readdir()方法可異步的讀取目錄內容,回調函數包含兩個參數,第一個是錯誤對象,第二個是一個包含文件名稱的數組,對應的同步方法是readdirSync()。在下面的示例中,當前目錄包含兩個文件,上一級目錄包含一個目錄名稱。
const fs = require('fs'); fs.readdir('./', (err, files) => { console.log(files); //[ 'demo.txt', 'index.js' ] }); fs.readdir('../', (err, files) => { console.log(files); //[ '1' ] });
其它處理目錄的方法還有opendir()、mkdir()等。
2)讀寫文件
在fs模塊中,可使用批量方法readFile()將文件內容一次性的加載到內存中,如下所示。
const fs = require('fs'); fs.readFile('./origin.txt', (err, buf) => { console.log(buf.toString()); //"hello Node.js" });
對應的寫入方法是writeFile(),如下所示,文件路徑、寫入內容和回調函數是必傳的參數。如果文件不存在,那麼會自動創建。
fs.writeFile('./target.txt', 'hello Node.js', (err) => { if (err) throw err; console.log('文件已被保存'); });
當文件很大時,像上面這樣直接讀取會有問題,可以改用流式方法createReadStream(),分批次的讀取文件,如下所示,每次只讀7個字節的內容。
const readable = fs.createReadStream('./origin.txt', {highWaterMark: 7}); readable.on("data", (chunk) => { /*************/ /* "hello N" /* "ode.js" /************/ console.log(chunk.toString()); });
通過管道方法pipe()將origin.txt中的內容寫入到target-stream.txt中,如下所示,對於不存在的文件,也會自動創建。
const writable = fs.createWriteStream('./target-stream.txt');
readable.pipe(writable);
3)文件描述
fs模塊的stat()方法可讀取文件的描述信息,如下所示。
fs.stat('./demo.txt', (err, stats) => {
console.log(stats);
});
回調函數中的stats參數是一個fs.Stats對象,其屬性如下所示。它還包含一些判斷方法,例如isDirectory()、isFile()等。
Stats { dev: 195650, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 36873221949682120, size: 13, blocks: undefined, atimeMs: 1586227933993.0217, mtimeMs: 1585882949091.0166, ctimeMs: 1586227933995.0222, birthtimeMs: 1586227933993.0217, atime: 2020-04-07T02:52:13.993Z, mtime: 2020-04-03T03:02:29.091Z, ctime: 2020-04-07T02:52:13.995Z, birthtime: 2020-04-07T02:52:13.993Z }
fs模塊還提供了fstat()方法,在功能上與stat()等價,只是fstat()方法的第一個參數是文件描述符。在POSIX系統中,文件描述符是一個正整數,它實際上是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表。當打開或創建一個文件時,就會被分配一個文件描述符。
在下面的示例中,open()方法的回調函數中包含一個fd參數(即文件描述符),搭配fstat()方法就能讀取文件信息。
fs.open('./demo.txt', 'r', (err, fd) => { fs.fstat(fd, (err, stats) => { console.log(stats); }); });
4)監控文件
fs模塊提供了兩種方法來監控文件:watch()和watchFile(),前者能監控文件或目錄的更改,後者只能監控文件的更改。
watch()方法的監聽器回調包含兩個參數,第一個是事件類型(包括rename和change),第二個是觸發事件的文件名稱,如下所示。
fs.watch('./demo.txt', (eventType, filename) => {
console.log(eventType, filename);
});
執行node命令后,每次更改demo.txt文件,就會在控制台打印出下面這條語句。
$ node index.js
change demo.txt
雖然watch()方法的性能優於watchFile()方法,但是watch()不是一個跨平台的方法,其表現在各個平台中並非百分百一致(例如filename參數不能保證提供),而watchFile()是跨平台的。
5)異步文件
fs.promises是Node提供的一組備用的異步文件系統方法,它們會返回Promise對象而不是通過回調來處理結果。例如以Promise的方式使用stat()方法,如下所示。
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。
const fsPromises = require('fs').promises; fsPromises.stat('./demo.txt').then(stats => { console.log(stats); });
二、網絡
Node可以處理的網絡協議包括HTTP、TCP、HTTPS等,本節將會重點分析HTTP協議。Node中的http模塊基於net、stream、events等模塊,提供了一系列的網絡傳輸的底層API,可創建HTTP服務器和客戶端,包含重定向、代理、上傳數據等功能。
1)HTTP服務器
通過http.createServer()方法就能創建HTTP服務器,其內部會調用net.Server()方法,返回一個http.Server實例。當服務被創建后,就能通過server.listen()方法監聽一個端口。
在下面的示例中,監聽的端口是8000,createServer()的回調函數包含兩個參數:req和res,分別表示HTTP的請求和響應,前者是IncomingMessage類(一個可讀流)的實例,後者是ServerResponse類(一個可寫流)的實例。__dirname是一個全局變量,保存着當前文件所處的路徑。
const http = require('http'); const fs = require('fs'); const server = http.createServer(function (req, res) { fs.readFile(__dirname + "/index.html", function (err, data) { if (err) { res.statusCode = 500; res.end(String(err)); } else { res.end(data); } }); }).listen(8000);
在回調函數中,可修改或解析響應報文,例如像上面當發生錯誤時,將狀態碼改成500。在瀏覽器中訪問http://localhost:8000,就能通過end()方法在頁面中輸出index.html的文件內容。
注意,必須調用響應對象的end()方法結束此次響應,如果省略,那麼頁面將會一直處於加載中,阻塞內容渲染。
http.Server包含一組事件,例如connection和request,如下所示。前者會在建立新的TCP流時觸發,後者會在每次請求服務器時觸發。
server.on("connection", function (socket) { console.log(connection"); }); server.on("request", function (req, res) { console.log('request'); });
2)重定向
3XX格式的狀態碼用於重定向,例如在Node中實現302跳轉,如下所示。
http.createServer(function (req, res) { if(req.url == '/strick') { res.writeHead(302, {'Location': 'http://www.pwstrick.com'}); } res.end(); }).listen(8000);
當瀏覽器訪問http://localhost:8000/strick時,才會執行重定向。writeHead()方法可一次性設置響應的狀態碼和所有的首部。如果只想設置單個響應首部,可以使用setHeader()方法。
3)上傳數據
在實際的業務開發中,免不了上傳數據的需求,例如表單提交、圖像上傳等。下面是一張form表單,包含一個文本框和一個提交按鈕。
<form action="http://localhost:8000" method="post"> <input type="text" name="name" /> <button type="submit">提交</button> </form>
點擊提交按鈕,會將整張表單提交到HTTP服務器(代碼如下所示),假設文本框中輸入的內容為“咖啡機strick”。
const http = require('http'); const querystring = require('querystring'); const server = http.createServer(function (req, res) { //聲明Content-Type響應首部,以免中文亂碼 res.setHeader("Content-Type", "application/json; charset=utf-8"); const arr = []; req.on("data", chunk => { arr.push(chunk); }); req.on("end", () => { const buf = Buffer.concat(arr); //拼接Buffer數據 const params = querystring.decode(buf.toString()); console.log(params.name); //"咖啡機strick" res.write(JSON.stringify(params)); //響應數據 res.end(); }); }).listen(8000);
在data事件中接收數據並添加到arr數組中,然後在end事件中由Buffer.concat()方法拼接Buffer數據。querystring模塊的decode()方法可將查詢字符串解析成一個對象。write()方法會將響應數據發送給客戶端。
4)客戶端服務
http模塊提供了request()方法,可讓客戶端向服務器發起請求。在下面的示例中,postData變量是要發送的數據,options變量是各種配置參數,包括請求首部的信息。
const http = require('http'); const querystring = require('querystring'); const postData = querystring.stringify({ 'name': '咖啡機strick' }); const options = { hostname: 'localhost', port: 8000, path: '/', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; const req = http.request(options, (res) => { const code = res.statusCode; //狀態碼 const headers = JSON.stringify(res.headers); //響應首部 res.setEncoding('utf8'); //為可讀流設置字符編碼 res.on('data', (chunk) => { console.log(chunk); //響應數據 }); res.on('end', () => { console.log('響應中已無數據'); }); }); req.write(postData); req.end();
注意,在請求最後需要調用end()方法,結束本次請求。Node還提供了一個基於request()的便捷方法:get(),它會自動調用req.end()方法,並且請求方法是GET。
5)代理
代理是一種特殊的網絡服務,允許一個客戶端通過這個服務與目標服務器進行間接的連接,也就是在它們之間建立了一層中轉,可用來過濾廣告、控制內部資源的訪問權限、保障終端的隱私或安全等。
http模塊可搭建出一個簡易的HTTP代理服務器,下面示例引用自《Node.js硬實戰》技巧52一節。
const http = require('http'); const url = require('url'); http.createServer(function (req, res) { const options = url.parse(req.url); //一個URL對象 options.headers = req.headers; req.on('data', chunk => { //將請求的原始數據發送給代理 proxyRequest.write(chunk); }); req.on('end', chunk => { //完成原始請求 proxyRequest.end(); }); //複製原始請求 const proxyRequest = http.request(options, proxyResponse => { proxyResponse.on('data', chunk => { //將響應的原始數據發送給客戶端 res.write(chunk); }); proxyResponse.on('end', chunk => { //完成代理請求 res.end(); }); //將響應報文發送給客戶端 res.writeHead(proxyResponse.statusCode, proxyResponse.headers); }); }).listen(8000);
url模塊的parse()方法能將字符串轉換成一個URL對象。在綁定請求對象的data事件后,就能將客戶端的請求數據發送給代理。通過http.request()方法發起一次代理請求,並將服務器的響應數據發送給客戶端。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。