欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

從零學(xué)習(xí)node.js之搭建http服務(wù)器(二)

 更新時(shí)間:2017年02月21日 09:41:02   作者:Wenzi  
NodeJs是什么我想大家已經(jīng)很了解了,作為一個(gè)前端工程師,想要不斷提升自己,一般都會(huì)接觸到后端服務(wù)器的技術(shù),NodeJs給我們提供了一個(gè)學(xué)習(xí)成本相對(duì)較低的捷徑可走。下面這篇文章主要介紹了node.js中搭建http服務(wù)器的相關(guān)資料,需要的朋友可以參考下。

前言

上篇文章中我們了解了一下不同模塊規(guī)范之間的聯(lián)系與區(qū)別。本文我們正式開(kāi)始node的學(xué)習(xí),首先我們從搭建一個(gè)http服務(wù)器,能運(yùn)行簡(jiǎn)單的程序開(kāi)始說(shuō)起。

一、hello world

最經(jīng)典的hello world。首先我們創(chuàng)建一個(gè)server.js來(lái)保存我們的代碼:

console.log( 'hello world' );

在終端輸入node server.js運(yùn)行:

node server.js

終端就會(huì)輸出 hello world 的字樣??墒俏覀円粋€(gè)node服務(wù)器程序,總是要在瀏覽器上訪問(wèn)的呀,這里就要用到node里自帶的http模塊了:

var http = require('http'); // 引入http模塊

// 創(chuàng)建http服務(wù)器
// request : 從瀏覽器帶來(lái)的請(qǐng)求信息
// response : 從服務(wù)器返回給瀏覽器的信息
http.createServer(function(request, response){
 response.writeHead(200, {'content-type': 'text/plain'}); // 設(shè)置頭部信息,輸出text文本
 response.write('hello world'); // 輸出到頁(yè)面中的信息
 response.end(); // 返回結(jié)束
}).listen(3000);
console.log('server has started...');

我們?cè)俅卧诮K端輸入node server.js運(yùn)行,終端里會(huì)有輸出 server has started… 的字樣,表示服務(wù)器已創(chuàng)建并正在運(yùn)行,然后我們?cè)跒g覽器上訪問(wèn)127.0.0.1:3000,就可以看到頁(yè)面中輸出了hello world。

二、form表單

剛才我們只是在頁(yè)面中輸出了一段簡(jiǎn)單的文本,現(xiàn)在我們要在頁(yè)面中呈現(xiàn)一個(gè)表單,可以讓用戶輸入信息并進(jìn)行提交:

// 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字符串輸出到頁(yè)面中
 response.end(); // 結(jié)束
}).listen(3000);
console.log('server has started...');

修改server.js中的內(nèi)容,重新運(yùn)行:

node server.js

刷新頁(yè)面后,我們發(fā)現(xiàn)頁(yè)面中輸出了3個(gè)文本框和1個(gè)提交按鈕。因?yàn)槲覀兊某绦蛑皇浅尸F(xiàn)頁(yè)面,并沒(méi)有做任何其他的處理,因此在頁(yè)面中提交數(shù)據(jù)只是刷新當(dāng)前頁(yè)面。

注意: 我們每次修改node中的任何代碼后,都要重新進(jìn)行啟動(dòng)。

2.1 獲取表單GET方式提交的數(shù)據(jù)

我們上面的代碼中使用的是POST方式,不過(guò)這里要先討論使用GET方式提交過(guò)來(lái)的數(shù)據(jù),我們先不考慮數(shù)據(jù)的安全性,只是學(xué)習(xí)如何獲取使用get方式提交過(guò)來(lái)的form表單數(shù)據(jù),將post改為get,重新運(yùn)行。

我們知道,使用get方式提交數(shù)據(jù),會(huì)將數(shù)據(jù)作為URL參數(shù)傳遞過(guò)來(lái),因此我們通過(guò)解析URL中的參數(shù)獲取到數(shù)據(jù),這里就用到了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(); // 結(jié)束
}).listen(3000);
console.log('server has started...');

我們?cè)俅芜\(yùn)行提交后就能在頁(yè)面中顯示出數(shù)據(jù)了。

url.parse是用來(lái)解析URL字符串的,并返回解析后的URL對(duì)象。若我們只輸出一下 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個(gè)參數(shù)設(shè)置為true,則會(huì)將返回結(jié)果中的query屬性解析為一個(gè)對(duì)象,其他屬性不變;默認(rèn)值為false,即query屬性是一個(gè)字符串:

url.parse(request.url, true);

result:
Url {
...
query: {
 username: '111113',
 password: '123',
 age: '122',
 submit: 'submit' },
...
}

因此我們可以通過(guò)如下語(yǔ)句判斷是否有提交數(shù)據(jù)并獲取提交數(shù)據(jù),然后再輸出到中即可:

var query = url.parse( request.url, true ).query;
/*
{
 username: '111113',
 password: '123',
 age: '122',
 submit: 'submit'
}
*/

2.2 獲取表單POST方式提交的數(shù)據(jù)

現(xiàn)在我們使用post方式來(lái)提交數(shù)據(jù)。因?yàn)镻OST請(qǐng)求一般都比較“重” (用戶可能會(huì)輸入大量的內(nèi)容),如果用阻塞的方式來(lái)處理處理,必然會(huì)導(dǎo)致用戶操作的阻塞。因此node將post數(shù)據(jù)拆分為很多小的數(shù)據(jù)塊,然后通過(guò)data事件(表示新的小數(shù)據(jù)塊到達(dá)了)和end事件傳遞這些小數(shù)據(jù)塊(表示所有的數(shù)據(jù)都已經(jīng)接收完畢)。 所以,我們的思路應(yīng)該是:在data事件中獲取數(shù)據(jù)塊,在end事件中操作數(shù)據(jù)。

// 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...');

這段代碼與上段代碼項(xiàng)目,主要有的幾個(gè)變化是:

  1. 不再引入url模塊, 改用引入querystring模塊。因?yàn)槲覀儾辉賹?duì)URL進(jìn)行操作了,也沒(méi)必要引入了;
  2. 使用request.method.toLowerCase()=='post'判斷當(dāng)前是否有數(shù)據(jù)提交;
  3. 在data事件進(jìn)行數(shù)據(jù)的拼接,在end事件中進(jìn)行的處理;
  4. response.end()寫(xiě)在了end事件內(nèi)部,因?yàn)閑nd事件是異步操作,因此必須得數(shù)據(jù)輸出完成之后才能執(zhí)行response.end()

我們?cè)诳刂婆_(tái)中可以看出,postData是這樣的一個(gè)字符串:

'username=123&password=123&age=23&submit=submit';

因此我們使用query.parse將postData解析為對(duì)象類型,以便獲取提交過(guò)來(lái)的數(shù)據(jù)。

三、路由

現(xiàn)在我們所有的邏輯都是在根目錄下進(jìn)行的,沒(méi)有按照url區(qū)分,這里我們按照功能進(jìn)行路由拆分。以上面的post請(qǐng)求為例,我們可以拆分為:頁(yè)面初始化和form提交后的處理。

頁(yè)面初始化:

// starter.js 頁(yè)面初始化

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;

展示獲取的數(shù)據(jù):

// uploader.js 展示獲取的數(shù)據(jù)
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中進(jìn)行路由選擇

// 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...');

我們?nèi)我飧淖僓RL地址,會(huì)看到輸出的每個(gè)地址的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/

因此我們就根據(jù)pathname進(jìn)行路由,對(duì)路由進(jìn)行方法映射:

// 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...');

如果匹配到路由 / ,則執(zhí)行 starter.start(request, response) ;如果匹配到路由 /show ,則執(zhí)行 uploader.upload(request, response) 。如果都沒(méi)匹配到,則顯示404。

四、 圖片上傳并顯示

在上面我們已經(jīng)能成功提交數(shù)據(jù)了,這里來(lái)講解如何進(jìn)行圖片上傳并顯示。使用node自帶的模塊處理起來(lái)非常的麻煩,這里我們使用別人已經(jīng)開(kāi)發(fā)好的formidable模塊進(jìn)行編寫(xiě),它對(duì)解析上傳的文件數(shù)據(jù)做了很好的抽象。

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 圖片上傳

首先我們進(jìn)行的是圖片上傳操作,首先我們要確保當(dāng)前目錄中存在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;

我們上傳圖片后跳轉(zhuǎn)到upload路徑,然后顯示出相應(yīng)的信息:

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 (中國(guó)標(biāo)準(zhǔn)時(shí)間),
 _writeStream: [Object]
 }
 }
}

我們?cè)俨榭磇mg目錄時(shí),就會(huì)發(fā)現(xiàn)我們剛才上傳的照片了。

4.2 圖片顯示

將圖片上傳到服務(wù)器后,怎樣才能把圖片顯示在瀏覽器上呢。這里我們就使用到了fs模塊來(lái)讀取文件,創(chuàng)建一個(gè)shower.js來(lái)專門(mén)展示圖片:

// shower.js
var fs = require('fs'),
url = require('url');

function show(request, response){
 var query = url.parse(request.url, true).query,
 imgurl = query.src;

 // 讀取圖片并進(jìn)行輸出
 // 這里讀取鏈接中的src參數(shù),指定讀取哪張圖片 /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 中進(jìn)行圖片的引用:

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();
});

五、綜合

剛才學(xué)習(xí)了上傳數(shù)據(jù)和上傳圖片,這里我們將其綜合一下,擬定一個(gè)題目:“設(shè)定用戶名密碼,并上傳頭像”。希望可以自己實(shí)現(xiàn)一下。

六、接口的實(shí)現(xiàn)

在第2部分學(xué)習(xí)了GET和POST請(qǐng)求,那么在這里寫(xiě)一個(gè)簡(jiǎn)單json或jsonp接口應(yīng)該不是什么難事兒了吧。

創(chuàng)建一個(gè) 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 // 添加
};

然后對(duì) http://127.0.0.1:3000/inter 進(jìn)行json請(qǐng)求或jsonp請(qǐng)求即可。

為大家提供一個(gè)查詢API的中文地址:https://pinggod.gitbooks.io/nodejs-doc-in-chinese/content

總結(jié)

好了,以上就是這篇文章的全部?jī)?nèi)容了,這節(jié)還是寫(xiě)了不少的內(nèi)容,最核心的就是講解如何搭建一個(gè)簡(jiǎn)單的http服務(wù)器,進(jìn)行數(shù)據(jù)和圖片的提交與處理,在最后稍微講了下接口的編寫(xiě),后面有機(jī)會(huì)的話,會(huì)再具體講解下接口的編寫(xiě)。下面會(huì)和大家分享node之文件操作,請(qǐng)大家繼續(xù)關(guān)注腳本之家。

相關(guān)文章

  • nodejs個(gè)人博客開(kāi)發(fā)第二步 入口文件

    nodejs個(gè)人博客開(kāi)發(fā)第二步 入口文件

    這篇文章主要為大家詳細(xì)介紹了nodejs個(gè)人博客開(kāi)發(fā)的入口文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 教你用十行node.js代碼讀取docx的文本

    教你用十行node.js代碼讀取docx的文本

    這篇文章主要給大家介紹了用十行node.js代碼讀取docx文本的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-03-03
  • node koa2實(shí)現(xiàn)上傳圖片并且同步上傳到七牛云存儲(chǔ)

    node koa2實(shí)現(xiàn)上傳圖片并且同步上傳到七牛云存儲(chǔ)

    這篇文章主要介紹了node koa2實(shí)現(xiàn)上傳圖片并且同步上傳到七牛云存儲(chǔ),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • NodeJS?基于?Dapr?構(gòu)建云原生微服務(wù)應(yīng)用快速入門(mén)教程

    NodeJS?基于?Dapr?構(gòu)建云原生微服務(wù)應(yīng)用快速入門(mén)教程

    Dapr?是一個(gè)可移植的、事件驅(qū)動(dòng)的運(yùn)行時(shí),它使任何開(kāi)發(fā)人員能夠輕松構(gòu)建出彈性的、無(wú)狀態(tài)和有狀態(tài)的應(yīng)用程序,并可運(yùn)行在云平臺(tái)或邊緣計(jì)算中,它同時(shí)也支持多種編程語(yǔ)言和開(kāi)發(fā)框架,本文重點(diǎn)介紹NodeJS云原生微服務(wù)應(yīng)用,感興趣的朋友一起看看吧
    2022-07-07
  • 基于Node.js的WebSocket通信實(shí)現(xiàn)

    基于Node.js的WebSocket通信實(shí)現(xiàn)

    這篇文章主要介紹了基于Node.js的WebSocket通信實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Kubernetes Node刪除鏡像的實(shí)現(xiàn)步驟

    Kubernetes Node刪除鏡像的實(shí)現(xiàn)步驟

    本文介紹了在Kubernetes集群中如何刪除節(jié)點(diǎn)上的鏡像,包括連接節(jié)點(diǎn)、查看鏡像列表、使用Docker命令刪除鏡像以及驗(yàn)證刪除結(jié)果的步驟,感興趣的可以了解一下
    2024-09-09
  • node跨域請(qǐng)求方法小結(jié)

    node跨域請(qǐng)求方法小結(jié)

    本篇文章主要介紹了node跨域請(qǐng)求方法小結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • koa框架的原理、功能,與基本使用方法概述

    koa框架的原理、功能,與基本使用方法概述

    這篇文章主要介紹了koa框架的原理、功能,與基本使用方法,結(jié)合實(shí)例形式分析了koa框架的基本功能、原理、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2023-04-04
  • 十大 Node.js 的 Web 框架(快速提升工作效率)

    十大 Node.js 的 Web 框架(快速提升工作效率)

    Node.js 系統(tǒng)含有多種不同的結(jié)構(gòu),如 MVC、全棧、REST API 和生成器等。這些結(jié)構(gòu)不僅提升了 Web 應(yīng)用的開(kāi)發(fā)效率,也優(yōu)化了開(kāi)發(fā)過(guò)程。在這里,我們收集整理了十個(gè)高效的 Node.js 框架,希望對(duì)你有幫助。
    2017-06-06
  • Node.js如何自動(dòng)審核團(tuán)隊(duì)的代碼

    Node.js如何自動(dòng)審核團(tuán)隊(duì)的代碼

    在項(xiàng)目開(kāi)發(fā)中,統(tǒng)一團(tuán)隊(duì)的代碼風(fēng)格很重要,本文介紹如何用Node.js來(lái)自動(dòng)審核,來(lái)提高您的開(kāi)發(fā)速度。
    2016-07-07

最新評(píng)論