完全基于node的web应用

node
js
web
fs
fs文件路径

事实上通常“正确的方式”一般都不简单。

这其中涉及了nodejs中服务端JavaScript,函数式编程,阻塞与非阻塞,回调,事件,内部和外部模块等问题,但是函数式编程,阻塞与非阻塞,回调,事件这些编程思想是通用的,值得学习。

Node入门

用例

  • 用户可以通过浏览器使用我们的应用。

  • 当用户请求http://domain/start时,可以看到一个欢迎页面,页面上有一个文件上传的表单。

  • 用户可以选择一个图片并提交表单,随后文件将被上传到http://domain/upload,该页面完成上传后会把图片显示在页面上。

模块

  • 提供一个web页面,需要http服务器

  • 需要一个路由处理URL请求,对应到请求处理程序(requet handle)。

  • 路由处理POST数据,把数据封装好后传递给请求处理程序。

  • 最终的请求处理程序。

  • 返回一个对应视图给浏览器。

  • 上传功能。

基本http服务器

  • server.js

    1. var http = require ("http"); 

    2. http.createServer(function (request,response){ 

    3. response.writeHead(200,{"Content-Type":"text/plain"}); 

    4. response.write("hello world"); 

    5. response.end(); 

    6. }).listen(8888); 

基于事件驱动回调

  • server.js

  1. var http = require("http"); 


  2. //这是一个事件回调函数 

  3. function onRequest(request, response) { 

  4. console.log("Request received."); 

  5. response.writeHead(200, {"Content-Type": "text/plain"}); 

  6. response.write("Hello World"); 

  7. response.end(); 



  8. //一旦由请求事件,onRequest函数被调用 

  9. http.createServer(onRequest).listen(8888); 


  10. console.log("Server has started."); 

模块化server

  • server.js

    1. var http = require("http"); 


    2. function start() { 

    3. function onRequest(request, response) { 

    4. console.log("Request received."); 

    5. response.writeHead(200, {"Content-Type": "text/plain"}); 

    6. response.write("Hello World"); 

    7. response.end(); 




    8. http.createServer(onRequest).listen(8888); 

    9. console.log("Server has started."); 



    10. //导出函数 

    11. exports.start = start; 

路由模块,依赖注入到service

  • router.js

    1. function route(pathname) { 

    2. console.log("About to route a request for " + pathname); 




    3. exports.route = route; 

  • server.js

    1. var http = require("http"); 

    2. var url = require("url"); 


    3. function start(route) { 

    4. function onRequest(request, response) { 

    5. var pathname = url.parse(request.url).pathname; 

    6. console.log("Request for " + pathname + " received."); 


    7. route(pathname);//依赖注入 


    8. response.writeHead(200, {"Content-Type": "text/plain"}); 

    9. response.write("Hello World"); 

    10. response.end(); 




    11. http.createServer(onRequest).listen(8888); 

    12. console.log("Server has started."); 




    13. exports.start = start; 

  • index.js


    1. var server = require("./server"); 

    2. var router = require("./router"); 


    3. server.start(router.route);//依赖注入 

行为驱动处理函数,函数式编程

  • requestHandlers.js

    1. //行为实现 

    2. function start() { 

    3. console.log("Request handler 'start' was called."); 

    4. return "Hello Start"; 




    5. function upload() { 

    6. console.log("Request handler 'upload' was called."); 

    7. return "Hello Upload"; 




    8. exports.start = start; 

    9. exports.upload = upload; 

  • index.js

    1. var server = require("./server"); 

    2. var router = require("./router"); 

    3. var requestHandlers = require("./requestHandlers"); 


    4. var handle = {}//根据路由执行行为定义 

    5. handle["/"] = requestHandlers.start; 

    6. handle["/start"] = requestHandlers.start; 

    7. handle["/upload"] = requestHandlers.upload; 


    8. server.start(router.route, handle); 

  • server.js

    1. var http = require("http"); 

    2. var url = require("url"); 


    3. function start(route, handle) { 

    4. function onRequest(request, response) { 

    5. var pathname = url.parse(request.url).pathname; 

    6. console.log("Request for " + pathname + " received."); 


    7. response.writeHead(200, {"Content-Type": "text/plain"}); 

    8. var content = route(handle, pathname) //路由行为分配 

    9. response.write(content); 

    10. response.end(); 



    11. http.createServer(onRequest).listen(8888); 

    12. console.log("Server has started."); 




    13. exports.start = start; 

  • router.js

    1. function route(handle, pathname) { 

    2. console.log("About to route a request for " + pathname); 

    3. //根据路由分配行为 

    4. if (typeof handle[pathname] === 'function') { 

    5. return handle[pathname](); 

    6. } else { 

    7. console.log("No request handler found for " + pathname); 

    8. return "404 Not found"; 






    9. exports.route = route; 

阻塞与非阻塞

nodeJS它通过事件轮询(event loop)来实现并行操作,所以尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。

要用非阻塞操作,我们需要使用回调。

回调就是:你继续处理你的事情,我(Node.js线程)先不等你了,我继续去处理你后面的代码,请你提供一个callbackFunction(),等你处理完之后我会去调用该回调函数的,谢谢!

阻塞的请求

  • requestHandlers.js

  1. function start() { 

  2. console.log("Request handler 'start' was called."); 


  3. function sleep(milliSeconds) { 

  4. var startTime = new Date().getTime(); 

  5. while (new Date().getTime() < startTime + milliSeconds); 



  6. sleep(10000); 

  7. return "Hello Start"; 




  8. function upload() { 

  9. console.log("Request handler 'upload' was called."); 

  10. return "Hello Upload"; 



  11. exports.start = start; 

  12. exports.upload = upload; 


处理POST请求

  • requestHandlers.js

    1. function start(response) { 

    2. console.log("Request handler 'start' was called."); 


    3. var body = '<html>'+ 

    4. '<head>'+ 

    5. '<meta http-equiv="Content-Type" content="text/html; '+ 

    6. 'charset=UTF-8" />'+ 

    7. '</head>'+ 

    8. '<body>'+ 

    9. '<form action="/upload" method="post">'+ 

    10. '<textarea name="text" rows="20" cols="60"></textarea>'+ 

    11. '<input type="submit" value="Submit text" />'+ 

    12. '</form>'+ 

    13. '</body>'+ 

    14. '</html>'; 


    15. response.writeHead(200, {"Content-Type": "text/html"}); 

    16. response.write(body); 

    17. response.end(); 




    18. function upload(response) { 

    19. console.log("Request handler 'upload' was called."); 

    20. response.writeHead(200, {"Content-Type": "text/plain"}); 

    21. response.write("Hello Upload"); 

    22. response.end(); 




    23. exports.start = start; 

    24. exports.upload = upload; 

request监听器

  • server.js

    1. var http = require("http"); 

    2. var url = require("url"); 


    3. function start(route, handle) { 

    4. function onRequest(request, response) { 

    5. var postData = "";//传输的数据 

    6. var pathname = url.parse(request.url).pathname; 

    7. console.log("Request for " + pathname + " received."); 


    8. request.setEncoding("utf8"); 

    9. //监听数据传输 

    10. request.addListener("data", function(postDataChunk) { 

    11. postData += postDataChunk; 

    12. console.log("Received POST data chunk '"+ 

    13. postDataChunk + "'."); 

    14. }); 

    15. //传输结束一次处理 

    16. request.addListener("end", function() { 

    17. route(handle, pathname, response, postData); 

    18. }); 





    19. http.createServer(onRequest).listen(8888); 

    20. console.log("Server has started."); 




    21. exports.start = start; 

数据传输给路由

  • router.js

    1. function route(handle, pathname, response, postData) { 

    2. console.log("About to route a request for " + pathname); 

    3. if (typeof handle[pathname] === 'function') { 

    4. handle[pathname](response, postData); 

    5. } else { 

    6. console.log("No request handler found for " + pathname); 

    7. response.writeHead(404, {"Content-Type": "text/plain"}); 

    8. response.write("404 Not found"); 

    9. response.end(); 






    10. exports.route = route; 

响应请求

  • requestHandlers.js

    1. var querystring = require("querystring"); 


    2. function start(response, postData) { 

    3. console.log("Request handler 'start' was called."); 


    4. var body = '<html>'+ 

    5. '<head>'+ 

    6. '<meta http-equiv="Content-Type" content="text/html; '+ 

    7. 'charset=UTF-8" />'+ 

    8. '</head>'+ 

    9. '<body>'+ 

    10. '<form action="/upload" method="post">'+ 

    11. '<textarea name="text" rows="20" cols="60"></textarea>'+ 

    12. '<input type="submit" value="Submit text" />'+ 

    13. '</form>'+ 

    14. '</body>'+ 

    15. '</html>'; 


    16. response.writeHead(200, {"Content-Type": "text/html"}); 

    17. response.write(body); 

    18. response.end(); 



    19. function upload(response, postData) { 

    20. console.log("Request handler 'upload' was called."); 

    21. response.writeHead(200, {"Content-Type": "text/plain"}); 

    22. response.write("You've sent the text: "+ 

    23. querystring.parse(postData).text); 

    24. response.end(); 




    25. exports.start = start; 

    26. exports.upload = upload; 

使用外部模块上传文件

node-formidable模块 安装

npm insatll formidable

npm install formidable -g express -d

node-formidable官方的例子

  1. var formidable = require('formidable'),
  2. http = require('http'),
  3. util = require('util');
  4. http.createServer(function(req, res) {
  5. if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
  6. // parse a file upload
  7. var form = new formidable.IncomingForm();
  8. form.parse(req, function(err, fields, files) {
  9. res.writeHead(200, {'content-type': 'text/plain'});
  10. res.write('received upload:\n\n');
  11. res.end(util.inspect({fields: fields, files: files}));
  12. });
  13. return;
  14. }
  15. // show a file upload form
  16. res.writeHead(200, {'content-type': 'text/html'});
  17. res.end(
  18. '<form action="/upload" enctype="multipart/form-data" '+
  19. 'method="post">'+
  20. '<input type="text" name="title"><br>'+
  21. '<input type="file" name="upload" multiple="multiple"><br>'+
  22. '<input type="submit" value="Upload">'+
  23. '</form>'
  24. );
  25. }).listen(8888);

读取图片数据

  • requestHandlers.js

    1. var querystring = require("querystring"), 

    2. fs = require("fs"); 


    3. function start(response, postData) { 

    4. console.log("Request handler 'start' was called."); 


    5. var body = '<html>'+ 

    6. '<head>'+ 

    7. '<meta http-equiv="Content-Type" '+ 

    8. 'content="text/html; charset=UTF-8" />'+ 

    9. '</head>'+ 

    10. '<body>'+ 

    11. '<form action="/upload" method="post">'+ 

    12. '<textarea name="text" rows="20" cols="60"></textarea>'+ 

    13. '<input type="submit" value="Submit text" />'+ 

    14. '</form>'+ 

    15. '</body>'+ 

    16. '</html>'; 


    17. response.writeHead(200, {"Content-Type": "text/html"}); 

    18. response.write(body); 

    19. response.end(); 




    20. function upload(response, postData) { 

    21. console.log("Request handler 'upload' was called."); 

    22. response.writeHead(200, {"Content-Type": "text/plain"}); 

    23. response.write("You've sent the text: "+ 

    24. querystring.parse(postData).text); 

    25. response.end(); 




    26. function show(response, postData) { 

    27. console.log("Request handler 'show' was called."); 

    28. fs.readFile("/tmp/test.png", "binary", function(error, file) { 

    29. if(error) { 

    30. response.writeHead(500, {"Content-Type": "text/plain"}); 

    31. response.write(error + "\n"); 

    32. response.end(); 

    33. } else { 

    34. response.writeHead(200, {"Content-Type": "image/png"}); 

    35. response.write(file, "binary"); 

    36. response.end(); 



    37. }); 




    38. exports.start = start; 

    39. exports.upload = upload; 

    40. exports.show = show; 

  • index.js

    1. var server = require("./server"); 

    2. var router = require("./router"); 

    3. var requestHandlers = require("./requestHandlers"); 


    4. var handle = {} 

    5. handle["/"] = requestHandlers.start; 

    6. handle["/start"] = requestHandlers.start; 

    7. handle["/upload"] = requestHandlers.upload; 

    8. handle["/show"] = requestHandlers.show; 


    9. server.start(router.route, handle); 

上传图片

  • requestHandlers.js

    1. var querystring = require("querystring"), 

    2. fs = require("fs"), 

    3. formidable = require("formidable"); 


    4. function start(response) { 

    5. console.log("Request handler 'start' was called."); 


    6. var body = '<html>'+ 

    7. '<head>'+ 

    8. '<meta http-equiv="Content-Type" content="text/html; '+ 

    9. 'charset=UTF-8" />'+ 

    10. '</head>'+ 

    11. '<body>'+ 

    12. '<form action="/upload" enctype="multipart/form-data" '+ 

    13. 'method="post">'+ 

    14. '<input type="file" name="upload" multiple="multiple">'+ 

    15. '<input type="submit" value="Upload file" />'+ 

    16. '</form>'+ 

    17. '</body>'+ 

    18. '</html>'; 


    19. response.writeHead(200, {"Content-Type": "text/html"}); 

    20. response.write(body); 

    21. response.end(); 




    22. function upload(response, request) { 

    23. console.log("Request handler 'upload' was called."); 


    24. var form = new formidable.IncomingForm(); 

    25. console.log("about to parse"); 

    26. form.parse(request, function(error, fields, files) { 

    27. console.log("parsing done"); 

    28. fs.renameSync(files.upload.path, "/tmp/test.png"); 

    29. response.writeHead(200, {"Content-Type": "text/html"}); 

    30. response.write("received image:<br/>"); 

    31. response.write("<img src='/show' />"); 

    32. response.end(); 

    33. }); 




    34. function show(response) { 

    35. console.log("Request handler 'show' was called."); 

    36. fs.readFile("/tmp/test.png", "binary", function(error, file) { 

    37. if(error) { 

    38. response.writeHead(500, {"Content-Type": "text/plain"}); 

    39. response.write(error + "\n"); 

    40. response.end(); 

    41. } else { 

    42. response.writeHead(200, {"Content-Type": "image/png"}); 

    43. response.write(file, "binary"); 

    44. response.end(); 



    45. }); 




    46. exports.start = start; 

    47. exports.upload = upload; 

    48. exports.show = show; 

  • server.js

    1. var http = require("http"); 

    2. var url = require("url"); 


    3. function start(route, handle) { 

    4. function onRequest(request, response) { 

    5. var pathname = url.parse(request.url).pathname; 

    6. console.log("Request for " + pathname + " received."); 

    7. route(handle, pathname, response, request); 




    8. http.createServer(onRequest).listen(8888); 

    9. console.log("Server has started."); 




    10. exports.start = start; 

fs模块的问题 文件路径问题

  1. function upload(response,request) { 

  2. console.log("Request handler 'upload' was called"); 

  3. // response.writeHead(200, { 

  4. // "Content-Type": "text/plain" 

  5. // }); 

  6. // response.write("you are sent: " + querystring.parse(postData).text); 

  7. // response.end(); 

  8. // response.write("hello upload"); 

  9. //return "hello upload"; 

  10. // 

  11. //文件上传 

  12. var form =new formidable.IncomingForm(); 

  13. console.log("start to parse"); 

  14. form.uploadDir = "tem"; 

  15. form.parse(request,function(error,fields,files){ 

  16. console.log("parsing done"); 

  17. try{ 

  18. fs.renameSync(files.upload.path,form.uploadDir+"/test.png");//主要修改了这个地方 

  19. }catch(e){ 

  20. console.log(e); 




  21. response.writeHead(200,{"Content-Type":"text/html"}); 

  22. response.write("received image:<br/>"); 

  23. response.write("<img src='/show'>"); 

  24. response.end(); 

  25. }) 



完全基于node的web应用的更多相关文章

  1. 转:基于node的web开发框架Express入门

    JavaScript 标准参考教程(alpha) 草稿二:Node.js Express框架 GitHub TOP Express框架 来自<JavaScript 标准参考教程(alpha)&g ...

  2. 基于Node的Web聊天室

    1 项目名称 Web聊天室(<这是NodeJs实战>第二章的一个案例,把整个开发过程记录下来)

  3. 基于 Node.js 平台,快速、开放、极简的 web 开发框架。

    资料地址:http://www.expressjs.com.cn/ Express 基于 Node.js 平台,快速.开放.极简的 web 开发框架. $ npm install express -- ...

  4. Fenix – 基于 Node.js 的桌面静态 Web 服务器

    Fenix 是一个提供给开发人员使用的简单的桌面静态 Web 服务器,基于 Node.js 开发.您可以同时在上面运行任意数量的项目,特别适合前端开发人员使用. 您可以通过免费的 Node.js 控制 ...

  5. KoaHub.js是基于 Koa.js 平台的 Node.js web 快速开发框架

    koahubjs KoaHub.js -- 基于 Koa.js 平台的 Node.js web 快速开发框架.可以直接在项目里使用 ES6/7(Generator Function, Class, A ...

  6. 基于 Koa.js 平台的 Node.js web 快速开发框架KoaHub.js demo 可安装

    KoaHub.js demo KoaHub.js KoaHub.js -- 基于 Koa.js 平台的 Node.js web 快速开发框架.可以直接在项目里使用 ES6/7(Generator Fu ...

  7. KoaHub.js -- 基于 Koa.js 平台的 Node.js web 快速开发框架之koahub-yilianyun

    koahub-yilianyun 微信易联云打印机接口 koahub-yilianyun易联云打印机node接口 Installation $ npm install koahub-yilianyun ...

  8. koa : Express出品的下一代基于Node.js的web框架

    https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434501579966a ...

  9. 认识Web前端、Web后端、桌面app和移动app新开发模式 - 基于Node.js环境和VS Code工具

    认识Web.桌面和移动app新开发模式 - 基于Node.js环境和VS Code工具 一.开发环境的搭建(基于win10) 1.安装node.js和npm 到node.js官网下载安装包(包含npm ...

随机推荐

  1. Jenkins(6)测试报告邮件发送

    前言 前面已经实现在jenkins上展示html的测试报告,接下来只差最后一步,把报告发给你的领导,展示你的劳动成果了. 安装 Email Extension Plugin 插件 jenkins首页- ...

  2. Kwp2000协议的应用(硬件原理使用篇)

    作者:良知犹存 转载授权以及围观:欢迎添加微信:becom_me 发现K线没有过多的文章描述,作为一个开发过K线的人,不写些文章帮助后来的人岂不是太浪费开发经验了呢. 总述     KWP2000是一 ...

  3. UDP发送文件

    接收端 package com.zy.demo2; import java.io.File; import java.io.FileOutputStream; import java.net.Data ...

  4. HDU6434 Count【欧拉函数 线性筛】

    HDU6434 I. Count T次询问,每次询问\(\sum_{i=1}^{n}\sum_{j=1}^{n-1}[gcd(i-j,i+j)=1]\) \(T\le 1e5, n \le 2e7\) ...

  5. Codeforces Round #640 (Div. 4)

    比赛链接:https://codeforces.com/contest/1352 A - Sum of Round Numbers 题意 将一个十进制数的每一个非零位分离出来. 代码 #include ...

  6. Codeforces Round #594 (Div. 2) C. Ivan the Fool and the Probability Theory (思维,递推)

    题意:给你一个\(n\)x\(m\)的矩阵,需要在这些矩阵中涂色,每个格子可以涂成黑色或者白色,一个格子四周最多只能有\(2\)个和它颜色相同的,问最多有多少种涂色方案. 题解:首先我们考虑一维的情况 ...

  7. 牛客编程巅峰赛S2第3场 Tree VI (树,dfs)

    题意:给你一个\(n\)个点的完全\(k\)叉树的先序遍历序列\(a\),还原这颗树并且求所有两个端点的异或和. 题解:用dfs在还原树的时候,把子节点和父亲节点的异或贡献给答案,对于每个节点,我们找 ...

  8. 一、Jmeter进行Mysql数据库的压测

    1.首先需要安装配置mysql数据库连接驱动:mysql-connector-java-5.1.28.jar 1.1 网上很多资源,可自行下载: 1.2 下载完成后,分别将该jra包,存放到:jmet ...

  9. Leetcode(106)-从中序与后序遍历序列构造二叉树

    根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15,7 ...

  10. 一个C++源文件从文本到可执行文件经历的过程

    一个C++源文件从文本到可执行文件经历的过程 以Hello World为例进行说明 首先我们编写一个cpp源程序 test.cpp #include <iostream> using na ...