摘要:在項目的文件夾下完成安裝依賴項。的主要功能是負責創建一個服務,然后對請求的路由進行判斷和過濾,交由模塊進行處理具體的請求路由。
上一節我們實現了手動控制路由的示例,這節我們來做一個完整的示例
目錄結構
基于前面的一些鋪墊,這節會做一個完整的示例。目錄的文件結構如下 :
</>復制代碼
- node-express-pug ==>項目目錄
- package.json ==>依賴文件
- server.js ==> 入口文件
- start.js ==> 創建服務
- router.js ==> 路由中轉
- handlers.js ==> 路由處理
- views/home.html ==>首頁
- files/ ==>存放上傳文件的目錄
- node_modules/ ==>依賴項文件目錄
package.json
首先我們安裝依賴項,本示例中的package.json文件如下:
</>復制代碼
{
"name": "application-name",
"version": "0.0.1",
"dependencies": {
"formidable": "latest",
"mime": "~1.3.4"
}
}
其中,formidable用于處理form表單數據,mime是一個互聯網標準類型,通過設定它就可以設定文件在瀏覽器的打開方式。稍后我們會看到如何使用它們。在項目的文件夾下npm install完成安裝依賴項。
server.js
首先我們來實現server.js。在server.js中,我們主要實現服務器的入口功能,調用各個模塊組件,由其他模塊實現具體的功能。
</>復制代碼
var server = require("./start");
var router = require("./router");
var handlers = require("./handlers");
var handler = {};
handler[["/","GET"]] = handlers.home;
handler[["/show","GET"]] = handlers.show;
handler[["/upload","POST"]] = handlers.upload;
server.start(router.route,handler);
先導入我們創建的其他的模塊文件,然后定義一個handlder對象,這里配置了對應的路由路徑和其對應的處理方法,類似handler[["/","GET"]] = handlers.home;,然后又調用了server模塊的start()方法,并傳入兩個參數,分別是router.route方法和handler對象。下面我們就來實現start.js文件。
start.js
start.js的主要功能是負責創建一個server服務,然后對請求的路由進行判斷和過濾,交由router模塊進行處理具體的請求路由。完整的代碼如下
</>復制代碼
//1.引用模塊
var http = require("http");
var url = require("url");
var formidable = require("formidable");
var querystring = require("querystring");
//2.start(route,handler)方法
//方法的參數是由上層傳遞過來,分別是router.route方法和handler對象
//其中route負責處理路由
//handler對象里是我們預先定義的可用處理的路由和對應的請求類型
function start(route,handler) {
console.log("Start Begin");
//3.監聽1337端口,創建服務器
var port = process.env.port || 1337;
http.createServer(onRequest).listen(port);
//4.創建服務器的回調方法
function onRequest(req, res) {
console.log("Request Begin");
//解析請求的路徑名
var pathname = url.parse(req.url).pathname;
var query = url.parse(req.url).query;
//POST方法處理
if (req.method === "POST"){
//解析form表單POST方式提交數據
var form = new formidable.IncomingForm();
//解析路徑的請求參數,包裝成data向下傳遞
//function (err, fields, files)是解析成功的回調方法
form.parse(req, function (err, fields, files) {
if (err){
console.error(err.message);
return;
}
var data = {fields:fields, files:files};
execute(pathname,handler,req, res, data);
});
}
//GET方法處理請求
if (req.method === "GET"){
var data = {
//解析路徑的請求參數,包裝成data向下傳遞
fields: querystring.parse(query)
};
execute(pathname,handler,req, res, data);
}
console.log("Request End");
}
//5.執行處理后的請求
function execute(pathname, handler, req, res, data) {
//route執行返回值,如果發生錯誤,統一返回400
var content = route(pathname,handler,req,res,data);
if (!content){
res.writeHead("400",{
"Content-Type":"text/plain"
});
console.log(req.url);
res.write("400 Bad Request");
res.end();
}
}
}
//6.導出模塊
exports.start = start;
這里注意
</>復制代碼
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) { });
form.parse會解析出很多的屬性,傳給回調參數files,下面是一個我上傳文件后打印的請求參數,參考如下:
</>復制代碼
{ fields: {},
files:
{ fn:
File {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
size: 4510,
path: "C:UsersADMINI~1AppDataLocalTempupload_5990006963ce4f2
9de485ddadd819355",
name: "sql.sql",
type: "application/octet-stream",
hash: null,
lastModifiedDate: 2017-03-10T07:00:14.577Z,
_writeStream: [Object]
}
}
}
router.js
我們看到最后的處理交給了var content = route(pathname,handler,req,res,data);,那么下面我們就來看router.js中route()方法的實現,完整的router.js如下:
</>復制代碼
function route(pathname,handler,req,res,data) {
console.log("Route");
var method = req.method;
if (typeof handler[[pathname,method]] === "function"){
return handler[[pathname,method]](res, data);
}else {
console.log("No Method found for " + pathname);
return null;
}
}
exports.route = route;
還記得我們的handler對象的格式嗎?我們的參數傳入了解析后的pathname,在這里又解析了請求的方式var method = req.method;。typeof handler[[pathname,method]] === "function",如果請求路由和請求不在我們的handler對象的中,即沒有指定的方法調用,那么我們就直接返回null,如果有,就調用這個方法。打個比方handler[["/show","get"]](res, data)等同于handlers.show(res, data)。
home.html
在home.html中我們定義了簡單的form表單,實現一個上傳文件的功能。
其中上傳文件的input標簽的name="fn".
</>復制代碼
HOME
This is Home
File Manager
Show All Files
handlers.js
這里才是我們對各個正確路由的響應。以下是完整的代碼,我會逐一解釋說明。
</>復制代碼
//1.引入模塊
var fs = require("fs");
var path = require("path");
var mime = require("mime");
//2.home方法,即瀏覽器請求`http://127.0.0.1:1337`的方法
//這里我們直接讀取views/home.html文件,返回將頁面展現出來
function home(res, data) {
fs.readFile("views/home.html", function (err, data) {
res.writeHead(200, {"Content-Type": "text/html"});
//注意這里的data并不是home的參數,而是讀取文件成功后的回調data
res.write(data);
res.end();
});
return true;
}
//3.show方法
//show方法會處理兩種類型的請求,兩種類型的請求都是get類型
//data.fields && data.fields["fn"] 這里處理的有上傳的文件后,點擊文件的鏈接下載文件
function show(res, data) {
//解析參數的data的值,這里用fn是因為后面form表單中定義的值是fn
if (data.fields && data.fields["fn"]){
//獲取文件名稱
var name = data.fields["fn"];
//取得文件完整名稱
var file = path.join(__dirname, "/files", name);
//通過文件名指定mime類型
var mimeType = mime.lookup(file);
//設定響應頭
res.setHeader("Content-disposition","attachment;filename=" + name);
res.setHeader("Content-Type",mimeType);
//讀取文件數據
var fileData = fs.readFileSync(file,"binary");
//響應給給用戶
res.end(fileData, "binary");
//這里會直接返回,并不會走下面的方法
return true;
}
//如果用戶不是點擊的下載鏈接進行show方法
//那么就讀取文件列表顯示在界面上,并且提供下載功能
fs.readdir("files", function (err, list) {
console.log(list);
res.writeHead(200, {"Content-Type": "text/html"});
var html = "" +
"File Manager
";
//有文件就生成文件列表
if (list.length) {
html += "";- for (i = 0; i < list.length; i++) {
- html += "
- " +
- list[i] + "
";- }
- html += "
";
} else {
//沒有文件
html += "No files found
";
}
html += "";
res.write(html);
res.end();
});
return true;
}
//4.上傳文件的方法,方法是響應home.html中的form表單
function upload(res, data) {
var temp = data.files["fn"].path;
var name = data.files["fn"].name;
//調用復制文件的方法
copyFile(temp,path.join("./files",name),function (err) {
if (err){
console.log(err);
return false;
}else {
return true;
}
});
}
//定義復制文件的方法
function copyFile(source, target, callback) {
//讀文件流
var rs = fs.createReadStream(source);
rs.on("error",function (err) {
callback(err);
});
//寫文件流
var ws = fs.createWriteStream(target);
ws.on("error",function (err) {
callback(err);
});
ws.on("finish",function () {
callback();
});
//寫入,并覆蓋源文件的內容
rs.pipe(ws);
}
//導出方法
exports.home = home;
exports.show = show;
exports.upload = upload;
小結
在項目文件夾下node server啟動http服務器,在瀏覽器中輸入http://127.0.0.1:1337
在上傳文件后點擊Show All Files,可以看到文件列表,點擊其中一個,即可下載。
這樣我們就完成了一個完整的node處理表單,文件上傳和下載的示例。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/18956.html
摘要:在項目的文件夾下完成安裝依賴項。的主要功能是負責創建一個服務,然后對請求的路由進行判斷和過濾,交由模塊進行處理具體的請求路由。 上一節我們實現了手動控制路由的示例,這節我們來做一個完整的示例 目錄結構 基于前面的一些鋪墊,這節會做一個完整的示例。目錄的文件結構如下 :showImg(https://segmentfault.com/img/bVKraD?w=186&h=214); ...
摘要:但是為什么執行的更快呢在這個系列文章中,我會為你解釋這一點。所以當人們說更快的時候,一般來講是與相比而言的。被人們廣為傳播的性能大戰在年打響。性能的提升使得的應用范圍得到很大的擴展。現在通過,我們很有可能正處于第二個拐點。 作者:Lin Clark 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce8036...
摘要:面向對象三大特征繼承性多態性封裝性接口。第五階段封裝一個屬于自己的框架框架封裝基礎事件流冒泡捕獲事件對象事件框架選擇框架。核心模塊和對象全局對象,,,事件驅動,事件發射器加密解密,路徑操作,序列化和反序列化文件流操作服務端與客戶端。 第一階段: HTML+CSS:HTML進階、CSS進階、div+css布局、HTML+css整站開發、 JavaScript基礎:Js基礎教程、js內置對...
閱讀 1563·2021-11-23 09:51
閱讀 1098·2021-10-12 10:12
閱讀 2818·2021-09-22 16:06
閱讀 3643·2019-08-30 15:56
閱讀 3470·2019-08-30 15:53
閱讀 3114·2019-08-29 16:29
閱讀 2367·2019-08-29 15:27
閱讀 2024·2019-08-26 10:49