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()方法暴露出去,以便其他模块调用
.
formidable 模块化开发 代码拆分(解耦) nodejs图片服务器架构的更多相关文章
- Windows平台网站图片服务器架构的演进[转]
构建在Windows平台之上的网站,往往会被业内众多架构师认为很“保守”.很大部分原因,是由于微软技术体系的封闭和部分技术人员的短视造成 的.由于长期缺乏开源支持,所以只能“闭门造车”,这样很容易形成 ...
- Windows平台网站图片服务器架构的演进
在主流的Web站点中,图片往往是不可或缺的页面元素,尤其在大型网站中,几乎都将面临“海量图片资源”的存储.访问等相关技术问题.在针对图片服务器的架构扩展中,也会历经很多曲折甚至是血泪教训(尤其是早期规 ...
- 前端模块化开发篇之grunt&webpack篇
几个月前写了一篇有关gulp和browserify来做前端构建的博客,因为browserify用来做js的打包时可能有些麻烦(特别是在写React的时候),所以这里再强烈推荐一款js打包工具-webp ...
- nginx+ftp搭建图片服务器(Windows Server服务器环境下)
几种图片服务器的对比 1.直接使用ftp服务器,访问图片路径为 ftp://账户:密码@192.168.0.106/31275-105.jpg 不采用这种方式,不安全容易暴露ftp账户信息 2.直接使 ...
- Javascript模块化开发,使用模块化脚本加载工具RequireJS,提高你代码的速度和质量。
随着前端JavaScript代码越来越重,如何组织JavaScript代码变得非常重要,好的组织方式,可以让别人和自己很好的理解代码,也便于维护和测试.模块化是一种非常好的代码组织方式,本文试着对Ja ...
- Js模块化开发的理解
Js模块化开发的理解 模块化是一个语言发展的必经之路,其能够帮助开发者拆分和组织代码,随着前端技术的发展,前端编写的代码量也越来越大,就需要对代码有很好的管理,而模块化能够帮助开发者解决命名冲突.管理 ...
- Android模块化开发实践
一.前言 随着业务的快速发展,现在的互联网App越来越大,为了提高团队开发效率,模块化开发已经成为主流的开发模式.正好最近完成了vivo官网App业务模块化改造的工作,所以本文就对模块化开发模式进行一 ...
- iOS关于模块化开发解决方案(纯干货)
关于iOS模块化开发解决方案网上也有一些介绍,但真正落实在在具体的实例却很少看到,计划编写系统文章来介绍关于我对模块化解决方案的理解,里面会有包含到一些关于解耦.路由.封装.私有Pod管理等内容:并编 ...
- Angular 结合RequireJs实现模块化开发
angular的指令是模块化很好的一个体现,下面我将只使用指令(不用控制器),结合requirejs,实现模块化开发. 模块化关系图:
随机推荐
- python中的enumerate使用
enumerate函数用于遍历序列中的元素以及它们的下标,多用于在for循环中得到计数,enumerate参数为可遍历的变量,如 字符串,列表等 一般情况下对一个列表或数组既要遍历索引又要遍历元素时, ...
- python基础(字符串常用、数字类型转换、基本运算符与流程控制)
一.字符串常用操作: #! /usr/bin/env python # -*- coding: utf-8 -*- # __author__ = "Z'N'Y" # Date: 2 ...
- Python 统一动态创建多个model对应的modelForm类(type()函数)
一.ModelForm的用法 ModelForm对用户提交的数据有验证功能,但比Form要简单的多 from django.forms import ModelForm # 导入ModelFormcl ...
- boost::Circular Buffer
boost.circular_buffer简介 很多时候,我们需要在内存中记录最近一段时间的数据,如操作记录等.由于这部分数据记录在内存中,因此并不能无限递增,一般有容量限制,超过后就将最开始的数据移 ...
- 中文名: 交通事故责任认定, 英文名称: Traffic accident responsibility identification
中文名: 交通事故责任认定, 英文名称: Traffic accident responsibility identification
- Spring MVC的工作机制
1. Spring MVC请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作. 2. DispatcherServlet查询一个或多个H ...
- 【BZOJ3167/4824】[Heoi2013]Sao/[Cqoi2017]老C的键盘
[BZOJ3167][Heoi2013]Sao Description WelcometoSAO(StrangeandAbnormalOnline).这是一个VRMMORPG,含有n个关卡.但是,挑战 ...
- 常见的 HTTP 状态代码及原因
代码 说明 备注 200 确定 IIS 7.0.IIS 7.5 和 IIS 8.0 成功处理了请求. 304 未修改 客户端浏览器请求已处于缓存中的文档,并且自从该文档被缓存后,未修改此文档.客户端浏 ...
- Saga的实现模式——进化(Saga implementation patterns – variations)
在之前的几个博客中,我主要讲了两个saga的实现模式: 基于command的控制者模式 基于事件的观察者模式 当然,这些都不是实现saga的唯一方式.我们甚至可以将这些结合起来. 发布者——收集者 回 ...
- 如何让vs2017 EF实体生成支持Mysql 和 Oracle?
1.Mysql 安装 MySql Connector/Net https://dev.mysql.com/downloads/connector/net/ 安装 mysql f ...