引言:程序要做到:健壮性、低耦合、可扩展、方便程序员分工合作
上传图片值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()方法暴露出去,以便其他模块调用
.