您好,登錄后才能下訂單哦!
前言
在上篇文章中我們了解了一下不同模塊規范之間的聯系與區別。本文我們正式開始node的學習,首先我們從搭建一個http服務器,能運行簡單的程序開始說起。
一、hello world
最經典的hello world。首先我們創建一個server.js來保存我們的代碼:
console.log( 'hello world' );
在終端輸入node server.js
運行:
node server.js
終端就會輸出 hello world 的字樣。可是我們一個node服務器程序,總是要在瀏覽器上訪問的呀,這里就要用到node里自帶的http模塊了:
var http = require('http'); // 引入http模塊 // 創建http服務器 // request : 從瀏覽器帶來的請求信息 // response : 從服務器返回給瀏覽器的信息 http.createServer(function(request, response){ response.writeHead(200, {'content-type': 'text/plain'}); // 設置頭部信息,輸出text文本 response.write('hello world'); // 輸出到頁面中的信息 response.end(); // 返回結束 }).listen(3000); console.log('server has started...');
我們再次在終端輸入node server.js
運行,終端里會有輸出 server has started…
的字樣,表示服務器已創建并正在運行,然后我們在瀏覽器上訪問127.0.0.1:3000,就可以看到頁面中輸出了hello world。
二、form表單
剛才我們只是在頁面中輸出了一段簡單的文本,現在我們要在頁面中呈現一個表單,可以讓用戶輸入信息并進行提交:
// server.js var http = require('http'); http.createServer(function(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/" method="post">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; response.writeHead(200, {'content-type': 'text/html'}); // 輸出html頭信息 response.write(html); // 將拼接的html字符串輸出到頁面中 response.end(); // 結束 }).listen(3000); console.log('server has started...');
修改server.js中的內容,重新運行:
node server.js
刷新頁面后,我們發現頁面中輸出了3個文本框和1個提交按鈕。因為我們的程序只是呈現頁面,并沒有做任何其他的處理,因此在頁面中提交數據只是刷新當前頁面。
注意: 我們每次修改node中的任何代碼后,都要重新進行啟動。
2.1 獲取表單GET方式提交的數據
我們上面的代碼中使用的是POST方式,不過這里要先討論使用GET方式提交過來的數據,我們先不考慮數據的安全性,只是學習如何獲取使用get方式提交過來的form表單數據,將post改為get,重新運行。
我們知道,使用get方式提交數據,會將數據作為URL參數傳遞過來,因此我們通過解析URL中的參數獲取到數據,這里就用到了url模塊中的方法:
// server.js var http = require('http'), url = require('url'); http.createServer(function(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/" method="get">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; var query = url.parse( request.url, true ).query; if( query.submit ){ var data = '<p><a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >back</a></p>'+ '<p>username:'+query.username+'</p>'+ '<p>password:'+query.password+'</p>'+ '<p>age:'+query.age+'</p>'; response.writeHead(200, {'content-type': 'text/html'}); response.write(data); }else{ response.writeHead(200, {'content-type': 'text/html'}); response.write(html); } response.end(); // 結束 }).listen(3000); console.log('server has started...');
我們再次運行提交后就能在頁面中顯示出數據了。
url.parse
是用來解析URL字符串的,并返回解析后的URL對象。若我們只輸出一下 url.parse(request.url)
:
url.parse(request.url); result: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: '?username=111113&password=123&age=122&submit=submit', query: 'username=111113&password=123&age=122&submit=submit', pathname: '/', path: '/?username=111113&password=123&age=122&submit=submit', href: '/?username=111113&password=123&age=122&submit=submit' }
如果將第2個參數設置為true,則會將返回結果中的query屬性解析為一個對象,其他屬性不變;默認值為false,即query屬性是一個字符串:
url.parse(request.url, true); result: Url { ... query: { username: '111113', password: '123', age: '122', submit: 'submit' }, ... }
因此我們可以通過如下語句判斷是否有提交數據并獲取提交數據,然后再輸出到中即可:
var query = url.parse( request.url, true ).query; /* { username: '111113', password: '123', age: '122', submit: 'submit' } */
2.2 獲取表單POST方式提交的數據
現在我們使用post方式來提交數據。因為POST請求一般都比較“重” (用戶可能會輸入大量的內容),如果用阻塞的方式來處理處理,必然會導致用戶操作的阻塞。因此node將post數據拆分為很多小的數據塊,然后通過data事件(表示新的小數據塊到達了)和end事件傳遞這些小數據塊(表示所有的數據都已經接收完畢)。 所以,我們的思路應該是:在data事件中獲取數據塊,在end事件中操作數據。
// server.js var http = require('http'), querystring = require('querystring'); http.createServer(function(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/" method="post">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; if( request.method.toLowerCase()=='post' ){ var postData = ''; request.addListener('data', function(chunk){ postData += chunk; }); request.addListener('end', function(){ var data = querystring.parse(postData); console.log( 'postData: '+postData ); console.log(data); var s = '<p><a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >back</a></p>'+ '<p>username:'+data.username+'</p>'+ '<p>password:'+data.password+'</p>'+ '<p>age:'+data.age+'</p>'; response.writeHead(200, {'content-type': 'text/html'}); response.write(s); response.end(); }) }else{ response.writeHead(200, {'content-type': 'text/html'}); response.write(html); response.end(); } }).listen(3000); console.log('server has started...');
這段代碼與上段代碼項目,主要有的幾個變化是:
querystring
模塊。因為我們不再對URL進行操作了,也沒必要引入了;request.method.toLowerCase()=='post'
判斷當前是否有數據提交;response.end()
寫在了end事件內部,因為end事件是異步操作,因此必須得數據輸出完成之后才能執行response.end()
我們在控制臺中可以看出,postData是這樣的一個字符串:
'username=123&password=123&age=23&submit=submit';
因此我們使用query.parse
將postData解析為對象類型,以便獲取提交過來的數據。
三、路由
現在我們所有的邏輯都是在根目錄下進行的,沒有按照url區分,這里我們按照功能進行路由拆分。以上面的post請求為例,我們可以拆分為:頁面初始化和form提交后的處理。
頁面初始化:
// starter.js 頁面初始化 function start(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/show" method="post">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; response.writeHead(200, {"Content-Type":"text/html"}); response.write( html ); response.end(); } exports.start = start;
展示獲取的數據:
// uploader.js 展示獲取的數據 var querystring = require('querystring'); function upload(request, response){ var postData = ''; request.addListener('data', function(chunk){ postData += chunk; }); request.addListener('end', function(){ var data = querystring.parse(postData); console.log( 'postData: '+postData ); console.log(data); var s = '<p><a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >back</a></p>'+ '<p>username:'+data.username+'</p>'+ '<p>password:'+data.password+'</p>'+ '<p>age:'+data.age+'</p>'; response.writeHead(200, {'content-type': 'text/html'}); response.write(s); response.end(); }) } exports.upload = upload;
然后在server.js中進行路由選擇
// server.js var http = require('http'), url = require('url'); http.createServer(function(request, response){ var pathname = url.parse(request.url).pathname; console.log(pathname); response.end(); }).listen(3000); console.log('server has started...');
我們任意改變URL地址,會看到輸出的每個地址的pathname(忽略/favicon.ico):
http://127.0.0.1:3000/ // 輸出: / http://127.0.0.1:3000/show/ // 輸出: /show/ http://127.0.0.1:3000/show/img/ // 輸出: /show/img/ http://127.0.0.1:3000/show/?username=wenzi // 輸出: /show/
因此我們就根據pathname進行路由,對路由進行方法映射:
// server.js var http = require('http'), url = require('url'), starter = require('./starter'), uploader = require('./uploader'); http.createServer(function(request, response){ var pathname = url.parse(request.url).pathname; var routeurl = { '/' : starter.start, '/show' : uploader.upload } if( typeof routeurl[pathname]=== 'function' ){ routeurl[pathname](request, response); }else{ console.log('404 not found!'); response.end(); } }).listen(3000); console.log('server has started...');
如果匹配到路由 / ,則執行 starter.start(request, response)
;如果匹配到路由 /show ,則執行 uploader.upload(request, response)
。如果都沒匹配到,則顯示404。
四、 圖片上傳并顯示
在上面我們已經能成功提交數據了,這里來講解如何進行圖片上傳并顯示。使用node自帶的模塊處理起來非常的麻煩,這里我們使用別人已經開發好的formidable模塊進行編寫,它對解析上傳的文件數據做了很好的抽象。
npm install formidable --save-dev
在starter.js中,我們添加上file控件:
// starter.js function start(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/upload" method="post" enctype="multipart/form-data">\ <p>file : <input type="file" name="upload" multiple="multiple" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; response.writeHead(200, {"Content-Type":"text/html"}); response.write( html ); response.end(); } exports.start = start;
4.1 圖片上傳
首先我們進行的是圖片上傳操作,首先我們要確保當前目錄中存在tmp和img目錄。
在 uploader.js 中:
// uploader.js var formidable = require('formidable'), util = require('util'), fs = require('fs'); function upload(request, response){ if( request.method.toLowerCase()=='post' ){ var form = new formidable.IncomingForm(); form.uploadDir = './tmp/'; form.parse(request, function(err, fields, files) { var oldname = files.upload.name, newname = Date.now() + oldname.substr(oldname.lastIndexOf('.')); fs.renameSync(files.upload.path, "./img/"+newname ); // 上傳到 img 目錄 response.writeHead(200, {'content-type': 'text/plain'}); response.write('received upload:\n\n'); response.end(util.inspect({fields: fields, files: files})); }); return; } } exports.upload = upload;
我們上傳圖片后跳轉到upload路徑,然后顯示出相應的信息:
received upload: { fields: { // 其他控件,如input, textarea等 submit: 'submit' }, files:{ // file控件 upload:{ domain: null, _events: {}, _maxListeners: undefined, size: 5097, path: 'tmp\\upload_b1f7c3e83af224e9f3a020958cde5dcd', name: 'chrome.png', type: 'image/png', hash: null, lastModifiedDate: Thu Jan 12 2017 23:09:50 GMT+0800 (中國標準時間), _writeStream: [Object] } } }
我們再查看img目錄時,就會發現我們剛才上傳的照片了。
4.2 圖片顯示
將圖片上傳到服務器后,怎樣才能把圖片顯示在瀏覽器上呢。這里我們就使用到了fs模塊來讀取文件,創建一個shower.js來專門展示圖片:
// shower.js var fs = require('fs'), url = require('url'); function show(request, response){ var query = url.parse(request.url, true).query, imgurl = query.src; // 讀取圖片并進行輸出 // 這里讀取鏈接中的src參數,指定讀取哪張圖片 /show?src=1484234660592.png fs.readFile('./img/'+imgurl, "binary", function(err, file){ if(err) throw err; response.writeHead(200, {"Content-Type": "image/png"}); response.write(file, "binary"); response.end(); }) } exports.show = show;
然后在 server.js 中添加上 show 的路由映射:
var routeurl = { '/' : starter.start, '/upload' : uploader.upload, '/show' : shower.show // 添加 };
最后在 upload.js 中進行圖片的引用:
form.parse(request, function(err, fields, files) { var oldname = files.upload.name, newname = Date.now() + oldname.substr(oldname.lastIndexOf('.')); fs.renameSync(files.upload.path, "./img/"+newname ); // 同步上傳圖片 response.writeHead(200, {'content-type': 'text/html'}); var s = '<p><a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >back</a></p><p><img src="/show?src='+newname+'" /></p>'; // 顯示剛才的圖片 response.write(s); response.end(); });
五、綜合
剛才學習了上傳數據和上傳圖片,這里我們將其綜合一下,擬定一個題目:“設定用戶名密碼,并上傳頭像”。希望可以自己實現一下。
六、接口的實現
在第2部分學習了GET和POST請求,那么在這里寫一個簡單json或jsonp接口應該不是什么難事兒了吧。
創建一個 inter.js :
// inter.js var url = require('url'); function init(request, response){ if( request.method.toLowerCase()=='get' ){ var query = url.parse(request.url, true).query; var data = {"code":0, "msg":"success", "data":[{"username":"wenzi", "age":26}, {"username":"bing", "age":25}]}; if( query && query.callback ){ // jsonp response.end( query.callback + '(' + JSON.stringify(data) + ')' ); }else{ // json response.end( JSON.stringify(data) ); } } } exports.init = init;
在server中添加inter的引用和路由映射:
var routeurl = { '/' : starter.start, '/upload' : uploader.upload, '/show' : shower.show, '/inter' : inter.init // 添加 };
然后對 http://127.0.0.1:3000/inter 進行json請求或jsonp請求即可。
為大家提供一個查詢API的中文地址:https://pinggod.gitbooks.io/nodejs-doc-in-chinese/content
總結
好了,以上就是這篇文章的全部內容了,這節還是寫了不少的內容,最核心的就是講解如何搭建一個簡單的http服務器,進行數據和圖片的提交與處理,在最后稍微講了下接口的編寫,后面有機會的話,會再具體講解下接口的編寫。下面會和大家分享node之文件操作,請大家繼續關注億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。