formidable 模块化开发 代码拆分(解耦) nodejs图片服务器架构

引言:程序要做到:健壮性、低耦合、可扩展、方便程序员分工合作

上传图片值nodejs服务器并显示图片的源代码:

post.html :

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>图片上传</title>
</head>
<body>
	<!--
	form表单:
	action 向何处发送表单数据(url)
	method 方法
	enctype 上传类型
	-->

	<form action="/upload" method="post" enctype="multipart/form-data">
		<!--描述-->
		<input type="text" name="description">
		<!--上传图片-->
		<input type="file" name="myFile">
		<!--提交按钮-->
		<input type="submit" value="点击提交">
	</form>
</body>
</html>

formidable_upload.js :

/**
 * 使用插件前,需要配置环境 npm install formidable
 * 扩展应用,使得上传到服务器的图片可以显示
 */
var formidable = require('formidable');
var http = require('http');
var util = require('util'); // 1.http 和 util 是nodejs的内核模块,不需要单独安装
var fs = require('fs'); // 4.引入文件模块fs

// 16.创建模块,定义函数封装
function start() { // 17.调用start()方法,启动HTTP服务器
  // 定义onRequest方法,接收并处理HTTP请求的
  function onRequest(request, response) { // 通过http模块创建一个服务器(http服务器)
    if (request.url === '/upload' && request.method.toLowerCase() === 'post') { // 对上传路径进行判断
      // 针对图片上传进行处理
      // 解析上传文件
      var form = new formidable.IncomingForm();

      form.uploadDir = "public/upload/"; // 10.设置图片上传路径
      form.parse(request, function(err, fields, files) {
        fs.renameSync(files.myFile.path,"tmp/test.png"); // 11.文件搬移(覆盖"tmp/test.png")
        response.writeHead(200, {'content-type': 'text/html'}); // 12.响应一个页面
        response.write('received image:<br/>');
        response.write("<img src='/show'>"); // 13.将图片展示出来
        response.end();
      });

      return;
    } else if(request.url === '/show') { // 3.扩展应用,使得上传到服务器的图片可以显示
      // 调试
      console.log("request for show is received");
      // 5.通过文件模块fs,将图片写入响应
      fs.readFile("tmp/test.png","binary",function(error, file) {
        if(error){ // 6.读取失败
          response.writeHead(500, {'content-type': 'text/plain'});  // writeHead自请求头 可以写回请求头
          console.log(error);
          response.write('500 服务器内部错误');
          response.end();
        } else { // 7.读取数据成功
          response.writeHead(200, {'content-type': 'image/png'});  // content-type 返回的文件格式
          response.write(file,"binary"); // 将文件以二进制的方式写到页面上
          response.end();
        }
      }); // 读取文件readFile("文件","读取方式 binary二进制",回调函数 通过回调函数进行响应)
      
      return;
    }

    // 展示上传文件表单
    var body = fs.readFileSync('./post.html');// 8.使用post.html替换掉固有的表单结构(response.end)
    response.writeHead(200, {'content-type': 'text/html'});
    response.write(body);
    response.end();
    // response.end(
    //   '<form action="/upload" enctype="multipart/form-data" method="post">'+
    //   '<input type="text" name="title"><br>'+
    //   '<input type="file" name="upload" multiple="multiple"><br>'+
    //   '<input type="submit" value="Upload">'+
    //   '</form>'
    // );
  }

  http.createServer(onRequest).listen(80,function(){ //15.将onRequest作为参数传到createServer()方法中
    // 9.设置服务器返回信息
    console.log("Server is starting on port 80.");
  }); // 2.改成web默认端口 80
}

exports.start = start;// 18.将start()方法暴露出去,以便外部调用

将formidable_upload.js进行优化 及 模块化开发:

index.js :

var server = require('./server.js');

server.start();

server.js :

/**
 * 主文件
 * 使用插件前,需要配置环境 npm install formidable
 * 扩展应用,使得上传到服务器的图片可以显示
 */
var http = require('http');
var url = require('url');// 20.引入url模块
var router = require('./router.js'); // 23.引入router.js

// 16.创建模块,定义函数封装
function start() { // 17.调用start()方法,启动HTTP服务器
  // 定义onRequest方法,接收并处理HTTP请求的
  function onRequest(request, response) { // 通过http模块创建一个服务器(http服务器)
    // // 方法一
    // if(request.url === '/aaa'){}
    // else if(request.url === '/bbb'){}
    // ...

    // // 方法二
    // switch (request.url) {
    //   case 'aaa':
    //     break;
    //   default:
    // }

    // 19.方法三:定义一个函数,并暴露给其他模块调用
    router.route(request, response); // 21.调用route()方法, pathname请求  response响应
  }

  http.createServer(onRequest).listen(80,function(){ //15.将onRequest作为参数传到createServer()方法中
    // 9.设置服务器返回信息
    console.log("Server is starting on port 80.");
  }); // 2.改成web默认端口 80
}

exports.start = start;// 18.将start()方法暴露出去,以便其他模块调用

router.js :

// 文件的处理 及 第三方插件的引用 代码拆分
var util = require('util'); // 1.http 和 util 是nodejs的内核模块,不需要单独安装
var url = require('url'); // 25.引入url模块
var requestHandler = require('./requestHandler.js'); // 41.引入requestHandler.js模块
var handle = requestHandler.handle; // 42.定义handle对象,并赋值
// 20.封装route函数进行请求的处理
function route(request, response){ // 通过route进行转发、响应
  // 24.将request整体引入,在route下进行统一的处理
  var pathname = url.parse(request.url).pathname; // 判断需求
  
  if(typeof(handle[pathname]) === "function"){
    console.log("about to route to handle" + pathname); // 交给具体的请求程序执行
    // 判读handle[pathname]的类型是方法,则执行这个方法
    handle[pathname](request, response);
  } else {
    // 38.特殊情况处理
    console.log(pathname);
    response.writeHead(404, {'content-type': 'text/plain'});
    response.write("404, Not Found.");
    response.end();
  }

  // if (pathname === '/upload' && request.method.toLowerCase() === 'post') { // 对上传路径进行判断
  //   console.log("request for upload is received. 请求已收到.");
    
  //   console.log("about to route to upload Handle 路由给upload请求处理函数.");
  //   uploadHandler.upload(request, response); // 27.调用uploadHandler()方法

  // } else if(pathname === '/show') { // 3.扩展应用,使得上传到服务器的图片可以显示
  //   // 调试
  //   console.log("request for show is received");

  //   console.log("about to route to show Handle 路由给show请求处理函数.");

  //   showHandler.show(request, response);// 31.调用show()方法
    
  // } else if(pathname === '/start') { // 33.创建上传点
  //   // 调试
  //   console.log("request for start is received");

  //   console.log("about to route to start Handle 路由给start请求处理函数.");
    
  //   startHandler.start(request, response); // 35.调用start()方法

  // } else { 
  //   // 38.特殊情况处理
  //   console.log(pathname);
  //   response.writeHead(404, {'content-type': 'text/plain'});
  //   response.write("404, Not Found.");
  //   response.end();
  // }
}

exports.route = route;// 22.将route()方法暴露出去,以便其他模块调用

requestHandler.js :

/**
 * 40.路由表/服务单
 */
var uploadHandler = require('./uploadHandler.js'); // 29.引入uploadHandler.js模块
var showHandler = require('./showHandler.js'); // 32.引入showHandler.js模块
var startHandler = require('./startHandler.js'); // 36.引入startHandler.js模块
// 39.通过对象取值的方式,替换掉if else
// 定义handle对象,用来保存 请求与请求处理函数 的关系
var handle = {};
handle['/upload'] = uploadHandler.upload;
handle['/show'] = showHandler.show;
handle['/start'] = startHandler.start;
handle['/'] = startHandler.start;// 根目录

exports.handle = handle;// 暴露路由表对象handle,以便其他模块调用

startHandler.js :

/**
 * 上传点
 */
var fs = require('fs');// 37.引入文件模板fs
// 34.定义start(),封装具体的处理方法
function start(request, response) {
  // 展示上传文件表单
  var body = fs.readFileSync('./post.html');// 8.使用post.html替换掉固有的表单结构(response.end)
  response.writeHead(200, {'content-type': 'text/html'});
  response.write(body);
  response.end();
  // response.end(
  //   '<form action="/upload" enctype="multipart/form-data" method="post">'+
  //   '<input type="text" name="title"><br>'+
  //   '<input type="file" name="upload" multiple="multiple"><br>'+
  //   '<input type="submit" value="Upload">'+
  //   '</form>'
  // );
}

exports.start = start;// 将start()方法暴露出去,以便其他模块调用

uploadHandler.js :

/**
 * 28.单独拿出,专门用来处理图片上传请求
 */
var formidable = require('formidable');
var fs = require('fs'); // 4.引入文件模块fs
// 26.定义uploadHandler,封装具体的处理方法
function upload(request, response) {
  // 针对图片上传进行处理
  // 解析上传文件
  var form = new formidable.IncomingForm();

  form.uploadDir = "public/upload/"; // 10.设置图片上传路径
  form.parse(request, function(err, fields, files) {
    fs.renameSync(files.myFile.path,"tmp/test.png"); // 11.文件搬移(覆盖"tmp/test.png")
    response.writeHead(200, {'content-type': 'text/html'}); // 12.响应一个页面
    response.write('received image:<br/>');
    response.write("<img src='/show'>"); // 13.将图片展示出来
    response.end();
  });
  return;
}

exports.upload = upload;// 29.upload()方法暴露出去,以便其他模块调用

showHandler.js :

/**
 * 单独取出,专门用于图片展示
 */
var fs = require('fs');// 32.引入文件模板fs
// 30.定义show()方法,封装图片展示的具体实现方法
function show(request, response) {
  // 5.通过文件模块fs,将图片写入响应
  fs.readFile("tmp/test.png","binary",function(error, file) {
    if(error){ // 6.读取失败
      response.writeHead(500, {'content-type': 'text/plain'});  // writeHead自请求头 可以写回请求头
      console.log(error);
      response.write('500 服务器内部错误');
      response.end();
    } else { // 7.读取数据成功
      response.writeHead(200, {'content-type': 'image/png'});  // content-type 返回的文件格式
      response.write(file,"binary"); // 将文件以二进制的方式写到页面上
      response.end();
    }
  }); // 读取文件readFile("文件","读取方式 binary二进制",回调函数 通过回调函数进行响应)
  return;
}

exports.show = show;// 将show()方法暴露出去,以便其他模块调用

.

原文地址:https://www.cnblogs.com/crazycode2/p/7076145.html