服務器,請求路由以及請求處理程序都已經完成了,下面讓我們按照此前的用例給網站添加交互:用戶選擇一個文件,上傳該文件,然后在瀏覽器中看到上傳的文件。 為了保持簡單,我們假設用戶只會上傳圖片,然后我們應用將該圖片顯示到瀏覽器中。
處理POST請求
我們顯示一個文本區(textarea)供用戶輸入內容,然后通過 POST 請求提交給服務器。最后,服務器接受到請求,通過處理程序將輸入的內容展示到瀏覽器中。
/start 請求處理程序用于生成帶文本區的表單,因此,我們將requestHandlers.js 修改為如下形式:
function start(response) {
console.log("Request handler 'start' was called.");
var body = '<html>' +
'<head>' +
'<meta http-equiv="Content-Type" content="text/html; ' +
'charset=UTF-8" />' +
'</head>' +
'<body>' +
'<form action="/upload" method="post">' +
'<textarea name="text" rows="20" cols="60"></textarea>' +
'<input type="submit" value="Submit text" />' +
'</form>' +
'</body>' +
'</html>';
response.writeHead(200, {
"Content-Type": "text/html"
});
response.write(body);
response.end();
}
function upload(response) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {
"Content-Type": "text/plain"
});
response.write("Hello Upload");
response.end();
}
exports.start = start;
exports.upload = upload;
<code>http://localhost:8888/start</code> 就可以看到簡單的表單了,要記得重啟服務器哦
余下的篇幅,我們來探討一個更有趣的問題: 當用戶提交表單時,觸發/upload 請求處理程序處理 POST 請求的問題。
我們需要告訴 Node.js 當這些事件觸發的時候,回調哪些函數。怎么告訴呢? 我們通過在 request 對象上注冊 監聽器 (listener) 來實現。這里的request 對象是每次接收到 HTTP 請求時候,都會把該對象傳遞給onRequest 回調函數。
先從 server.js 開始:
var http = require("http");
var url = require("url");
function start(route, handle) {
function onRequest(request, response) {
var postData = "";
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
request.setEncoding("utf8");
request.addListener("data", function(postDataChunk) {
postData += postDataChunk;
console.log("Received POST data chunk '" +
postDataChunk + "'.");
});
request.addListener("end", function() {
route(handle, pathname, response, postData);
});
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
上述代碼做了三件事情: 首先,我們設置了接收數據的編碼格式為 UTF-8,然后注冊了“data”事件的監聽器,用于收集每次接收到的新數據塊,并將其賦值給 postData 變量,最后,我們將請求路由的調用移到 end 事件處理程序中,以確保它只會當所有數據接收完畢后才觸發,并且只觸發一次。我們同時還把 POST 數據傳遞給請求路由,因為這些數據,請求處理程序會用到。
上述代碼在每個數據塊到達的時候輸出了日志,這對于最終生產環境來說,是很不好的(數據量可能會很大,還記得吧?),但是,在開發階段是很有用的,有助于讓我們看到發生了什么。我建議可以嘗試下,嘗試著去輸入一小段文本,以及大段內容,當大段內容的時候,就會發現 data 事件會觸發多次。
再來點酷的。我們接下來在/upload 頁面,展示用戶輸入的內容。要實現該功能,我們需要將 postData 傳遞給請求處理程序,修改 router.js 為如下形式:
function route(handle, pathname, response, postData) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](response, postData);
} else {
console.log("No request handler found for " + pathname);
response.writeHead(404, {
"Content-Type": "text/plain"
});
response.write("404 Not found");
response.end();
}
}
exports.route = route;
然后,在 requestHandlers.js 中,我們將數據包含在對 upload 請求的響應中:
function start(response, postData) {
console.log("Request handler 'start' was called.");
var body = '<html>' +
'<head>' +
'<meta http-equiv="Content-Type" content="text/html; ' +
'charset=UTF-8" />' +
'</head>' +
'<body>' +
'<form action="/upload" method="post">' +
'<textarea name="text" rows="20" cols="60"></textarea>' +
'<input type="submit" value="Submit text" />' +
'</form>' +
'</body>' +
'</html>';
response.writeHead(200, {
"Content-Type": "text/html"
});
response.write(body);
response.end();
}
function upload(response, postData) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {
"Content-Type": "text/plain"
});
response.write("You've sent: " + postData);
response.end();
}
exports.start = start;
exports.upload = upload;
我們可以使用 querystring 模塊來實現,requestHandler.js代碼:
var querystring = require("querystring");
function start(response, postData) {
console.log("Request handler 'start' was called.");
var body = '<html>' +
'<head>' +
'<meta http-equiv="Content-Type" content="text/html; ' +
'charset=UTF-8" />' +
'</head>' +
'<body>' +
'<form action="/upload" method="post">' +
'<textarea name="text" rows="20" cols="60"></textarea>' +
'<input type="submit" value="Submit text" />' +
'</form>' +
'</body>' +
'</html>';
response.writeHead(200, {
"Content-Type": "text/html"
});
response.write(body);
response.end();
}
function upload(response, postData) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {
"Content-Type": "text/plain"
});
response.write("You've sent the text: " +
querystring.parse(postData).text);
response.end();
}
exports.start = start;
exports.upload = upload;
好了,以上就是關于處理 POST 數據的全部內容。