服务器,请求路由以及请求处理程序都已经完成了,下面让我们按照此前的用例给网站添加交互:用户选择一个文件,上传该文件,然后在浏览器中看到上传的文件。 为了保持简单,我们假设用户只会上传图片,然后我们应用将该图片显示到浏览器中。
处理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 数据的全部内容。