摘要:不使用框架創(chuàng)建簡單的應(yīng)用需求創(chuàng)建一個可以上傳圖片的應(yīng)用。自定義模塊剛才我們定義了一個簡單的服務(wù)。處理數(shù)據(jù)存儲本地安裝服務(wù)安裝客戶端使用命令行新建文件修改待續(xù)如何使用創(chuàng)建一個代理服務(wù)器的適用場景
不使用框架創(chuàng)建簡單的Node.js web應(yīng)用
需求: 創(chuàng)建一個可以上傳圖片的web應(yīng)用。用戶可以瀏覽應(yīng)用,有一個文件上傳的表單。選擇圖片上傳,上傳完成之后可以預(yù)覽圖片。上傳的圖片信息需要入庫(mysql)。一個簡單的http服務(wù)
const http = require("http"); // 創(chuàng)建一個服務(wù) const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello World"); }); // 服務(wù)錯誤監(jiān)聽 server.on("clientError", (err, socket) => { socket.end("HTTP/1.1 400 Bad Request "); }); // 當(dāng)前服務(wù)監(jiān)聽的端口 server.listen(8888); console.log("Server has started.");
涉及到的api:
http.createServer
res.writeHead
res.end
當(dāng)我們在編寫node服務(wù)的時候,如果服務(wù)器有異常,那node服務(wù)就直接掛掉了。那如何保證我們的node服務(wù)不會關(guān)閉,并且會自動重啟呢?
或者是我們修改了代碼,如何實(shí)現(xiàn)修改的代碼直接生效而不用重新手動重啟node服務(wù)呢?
npm install -g nodemon
在生產(chǎn)環(huán)境我一般使用pm2來管理node服務(wù)。
自定義模塊剛才我們定義了一個簡單的http服務(wù)。其中http是一個內(nèi)置的模塊。那其實(shí)我們的服務(wù)都會有一個入口文件,在這里我們定義為index.js。那我們?nèi)绾蜗褚胔ttp內(nèi)置模塊一樣,在index.js里使用server.js呢?
exports 與 module.exports 的區(qū)別:
exports是module.exports的簡寫。如果修改了exports的引用,也就是重新給exports賦值,則exports只是在當(dāng)前文件級作用域內(nèi)可用,并且exports的修改不會影響到module.exports的值。
server.js
const http = require("http"); function start() { const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello World"); }); server.on("clientError", (err, socket) => { socket.end("HTTP/1.1 400 Bad Request "); }); server.listen(8888); console.log("Server has started."); } // 通過給exports添加【屬性值】的方式導(dǎo)出方法 // 或者通過給module.exports添加屬性值 exports.start = start;
index.js
const server = require("./server"); server.start();
node index.js路由處理
我們知道,訪問一個web網(wǎng)站會有不同的頁面或者會調(diào)用不同的接口,那這些就對應(yīng)這不同的請求路徑,同時這些請求還會對應(yīng)不同的請求方法(GET, POST等)。那node如何針對這些不同的請求路徑去匹配對應(yīng)的處理函數(shù)呢?
為了處理http請求的參數(shù),我們需要獲取到http請求的request,從中獲取到請求方式以及請求路徑。在這里會依賴 url內(nèi)置模塊。
首先建立routes文件夾存放路由處理
routes/index.js
module.exports = (req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello World"); }
routes/upload.js
module.exports = (req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("upload file"); }
新建route.js文件處理路由
function route(handle, pathname, req, res) { if (typeof handle[pathname] === "function") { handle[pathname](req, res); } else { console.log("No request handler found for " + pathname); res.end("404 Not found"); } } exports.route = route;
修改server.js
const http = require("http"); const url = require("url"); const routes = {}; function use(path, routeHandler) { routes[path] = routeHandler; } function start(route) { function handleRequest(req, res) { const pathname = url.parse(req.url).pathname; route(routes, pathname, req, res) } const server = http.createServer(handleRequest); server.on("clientError", (err, socket) => { socket.end("HTTP/1.1 400 Bad Request "); }); server.listen(8888); console.log("Server has started."); } module.exports = { start, use };
修改index.js
const server = require("./server"); const index = require("./routes/index"); const upload = require("./routes/upload"); const router = require("./route"); server.use("/", index); server.use("/upload", upload); server.start(router.route);處理POST請求
我們顯示一個文本區(qū)(textarea)供用戶輸入內(nèi)容,然后通過POST請求提交給服務(wù)器。最后,服務(wù)器接受到請求,通過處理程序?qū)⑤斎氲膬?nèi)容展示到瀏覽器中。
給request注冊監(jiān)聽事件
request.addListener("data", function(chunk) { // called when a new chunk of data was received }); request.addListener("end", function() { // called when all chunks of data have been received });
querystring登場,解析上傳數(shù)據(jù)
修改server.js里的handleRequest方法
function handleRequest(req, res) { const pathname = url.parse(req.url).pathname; let postData = ""; // 設(shè)置編碼 req.setEncoding("utf8"); req.addListener("data", function(postDataChunk) { postData += postDataChunk; console.log("Received POST data chunk ""+ postDataChunk + ""."); }); req.addListener("end", function() { route(routes, pathname, req, res, postData); }); }
route.js多加一個參數(shù)postData
function route(handle, pathname, req, res, postData) { if (typeof handle[pathname] === "function") { handle[pathname](req, res, postData); } else { console.log("No request handler found for " + pathname); res.end("404 Not found"); } } exports.route = route;
index.js
const exec = require("child_process").exec; module.exports = (req, res, postData) => { // 可以使用node模板 const body = ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""; res.end(body); }
upload.js 修改
const querystring = require("querystring"); module.exports = (req, res, postData) => { const content = querystring.parse(postData).text; res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8"}); res.end(content || "Empty"); }處理文件上傳
npm install formidable
server.js修改
function handleRequest(req, res) { const pathname = url.parse(req.url).pathname; route(routes, pathname, req, res); }
routes/index.js
const exec = require("child_process").exec; module.exports = (req, res) => { // 可以使用node模板 const body = ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""; res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"}); res.end(body); }
showFile.js獲取磁盤圖片信息
const fs = require("fs"); const path = require("path"); function show(req, res) { const rootPath = path.resolve(); fs.readFile(`${rootPath}/tmp/test.png`, "binary", function(error, file) { if(error) { res.writeHead(500, {"Content-Type": "text/plain"}); res.write(error + " "); res.end(); } else { res.writeHead(200, {"Content-Type": "image/png"}); res.write(file, "binary"); res.end(); } }); } module.exports = show;
routes/uoload.js
const fs = require("fs"); const formidable = require("formidable"); const path = require("path"); module.exports = (req, res) => { const form = new formidable.IncomingForm(); const rootPath = path.resolve(); form.parse(req, function(error, fields, files) { console.log("parsing done"); fs.renameSync(files.upload.path, `${rootPath}/tmp/test.png`); res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"}); res.write("received image:
"); res.write(""); res.end(); }); }
同時在index.js中添加相應(yīng)的路由。
處理數(shù)據(jù)存儲本地安裝mysql服務(wù)
安裝mysql客戶端/使用命令行
npm install mysql
CREATE SCHEMA `nodestart` ; CREATE TABLE `nodestart`.`file` ( `id` INT NOT NULL AUTO_INCREMENT, `filename` VARCHAR(300) NULL, `path` VARCHAR(500) NULL, `size` VARCHAR(45) NULL, `type` VARCHAR(45) NULL, `uploadtime` VARCHAR(45) NULL, PRIMARY KEY (`id`));
新建db.js文件
const mysql = require("mysql"); const connection = mysql.createConnection({ host : "localhost", user : "root", password : "123456", database : "nodestart" }); function query(sql, params) { return new Promise((resolve, reject) => { connection.connect(); connection.query(sql, params, function (error, results, fields) { if (error) reject(error); console.log("The solution is: ", results); resolve(fields); }); connection.end(); }); } exports.query = query;
修改routes/upload.js
const fs = require("fs"); const formidable = require("formidable"); const path = require("path"); const db = require("../db"); module.exports = (req, res) => { const form = new formidable.IncomingForm(); const rootPath = path.resolve(); form.parse(req, function(error, fields, files) { console.log("parsing done"); fs.renameSync(files.upload.path, `${rootPath}/tmp/test.png`); const fileObj = { size: files.upload.size, path: `${rootPath}/tmp/test.png`, filename: files.upload.name, type: files.upload.type, uploadtime: Date.now() } db.query("insert into nodestart.file set ?", fileObj).then((res) => { console.log(res) }).catch((err) => { console.log(err); }) res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"}); res.write("received image:
"); res.write(""); res.end(); }); }
待續(xù):
如何使用Node創(chuàng)建一個代理服務(wù)器 Node 的適用場景文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105738.html
摘要:在年成為最大贏家,贏得了實(shí)現(xiàn)的風(fēng)暴之戰(zhàn)。和他的競爭者位列第二沒有前端開發(fā)者可以忽視和它的生態(tài)系統(tǒng)。他的殺手級特性是探測功能,通過檢查任何用戶的功能,以直觀的方式讓開發(fā)人員檢查所有端點(diǎn)。 2016 JavaScript 后起之秀 本文轉(zhuǎn)載自:眾成翻譯譯者:zxhycxq鏈接:http://www.zcfy.cc/article/2410原文:https://risingstars2016...
摘要:在,是當(dāng)之無愧的王者,贏得了與之間的戰(zhàn)爭,攻陷了的城池。于月發(fā)布了版本,這一版本為了更好的表現(xiàn)加入了渲染方式。前端框架這個前端框架清單可能是年疲勞的元兇之一。的創(chuàng)建者,目前在工作為尋找構(gòu)建簡單性和自主配置性之間的平衡做了很大的貢獻(xiàn)。 春節(jié)后的第一篇就從這個開始吧~本文已在前端早讀課公眾號上首發(fā) 原文鏈接 JavasScript社區(qū)在創(chuàng)新的道路上開足了馬力,曾經(jīng)流行過的也許一個月之后就過...
摘要:它不僅從前端移動到后端,我們也開始看到它用于機(jī)器學(xué)習(xí)和增強(qiáng)現(xiàn)實(shí),簡稱。由于其高使用率,年的現(xiàn)狀調(diào)查將其稱為采用的安全技術(shù)。機(jī)器學(xué)習(xí)框架在年的開發(fā)者峰會上,宣布了他們的機(jī)器學(xué)習(xí)框架的實(shí)現(xiàn),稱為。更高級別的用于在之上構(gòu)建機(jī)器學(xué)習(xí)模型。 2019,開發(fā)者應(yīng)該學(xué)習(xí)的16個JavaScript框架 showImg(https://segmentfault.com/img/remote/14600...
摘要:轉(zhuǎn)載來源包管理器管理著庫,并提供讀取和打包它們的工具。能構(gòu)建更好應(yīng)用的客戶端包管理器。一個整合和的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。很棒的組件集合。隱秘地使用和用戶數(shù)據(jù)。 轉(zhuǎn)載來源:https://github.com/jobbole/aw... 包管理器管理著 javascript 庫,并提供讀取和打包它們的工具。?npm – npm 是 javasc...
摘要:轉(zhuǎn)載來源包管理器管理著庫,并提供讀取和打包它們的工具。能構(gòu)建更好應(yīng)用的客戶端包管理器。一個整合和的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。很棒的組件集合。隱秘地使用和用戶數(shù)據(jù)。 轉(zhuǎn)載來源:https://github.com/jobbole/aw... 包管理器管理著 javascript 庫,并提供讀取和打包它們的工具。?npm – npm 是 javasc...
摘要:一個專注于瀏覽器端和兼容的包管理器。一個整合和的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。完全插件化的工具,能在中識別和記錄模式。健壯的優(yōu)雅且功能豐富的模板引擎。完整的經(jīng)過充分測試和記錄數(shù)據(jù)結(jié)構(gòu)的庫。 【導(dǎo)讀】:GitHub 上有一個 Awesome – XXX 系列的資源整理。awesome-javascript 是 sorrycc 發(fā)起維護(hù)的 JS 資源列表...
閱讀 2672·2021-11-25 09:43
閱讀 2579·2021-11-22 09:34
閱讀 2823·2021-11-12 10:34
閱讀 1431·2021-10-20 13:46
閱讀 2301·2019-08-30 13:21
閱讀 929·2019-08-30 11:21
閱讀 483·2019-08-30 11:20
閱讀 2186·2019-08-29 17:20