目的:使用Node.js实现文件上传并将上传的文件显示到浏览器中
基本工具:Node.js,在windows下需要下载cygwin64来运行shell命令
文件:服务器模块、请求路由模块、请求处理程序模块、index.js入口文件
步骤:在目录中创建server.js、router.js、requestHandlers、index.js这文件,分别代表以上几个文件。
步骤一:在index.js文件中使用require引入以上模块,
const server = require(‘./server‘); const router = require(‘./router‘); const requestHandlers = require(‘./requestHandlers‘);
接着在index.js文件中需要定义路由,我们首先定义一个handle对象,用于保存路由,然后对应请求处理程序模块中的提供的方法(还没写)
//定义路由 let handle = {}; handle[‘/‘] = requestHandlers.start; handle[‘/start‘] = requestHandlers.start; handle[‘/upload‘] = requestHandlers.upload; handle[‘/show‘] = requestHandlers.show;
最后调用引入的服务器模块提供的方法server.start();并传入两个参数,第一个参数是请求路由模块提供的路径方法router.route,第二个参数是用于定义路由的handle对象
server.start(router.route,handle);
index.js文件的代码如上
步骤二:在请求处理程序模块requestHandlers.js文件中,我们需要引入fs模块用于读取文件,formidable模块用于格式化上传的表单
const fs = require(‘fs‘); const formidable = require(‘formidable‘);
接着我们来完善之前在index,js文件中对应的方法,在requestHandlers.js文件中,接着写下exports.start方法,这个方法接收一个参数res,届时将在服务器模块中传入该响应参数
exports.start = (res)=>{//服务器传入的响应参数 console.log("Request handler ‘start‘ was called."); res.writeHead(200, {"Content-Type": "text/html"});//告诉浏览器文件格式 let body = ‘<html>‘+ ‘<head>‘+ ‘<meta http-equiv="Content-Type" content="text/html; ‘+ ‘charset=UTF-8" />‘+ ‘</head>‘+ ‘<body>‘+ ‘<form action="/upload" enctype="multipart/form-data" method="post">‘+//修改文件编码 ‘<input type="file" name="upload">‘+ ‘<input type="submit" value="上传文件" />‘+ ‘</form>‘+ ‘</body>‘+ ‘</html>‘; res.end(body);//响应浏览器,并将body参数传进入 };
exports.upload = (res,req)=>{//对上传的文件进行处理 console.log("Request handler ‘upload‘ was called."); let form = new formidable.IncomingForm(); //对上传的文件进行处理 console.log(‘对上传的文件进行处理‘); form.parse(req,(err,fields,files)=>{ //上传的文件处理完毕 console.log(‘上传的文件处理完毕‘); console.log(files.upload.path); fs.renameSync(files.upload.path,"/tmp/test.png");//将路径一的文件保存到路径二 res.writeHead(200,{"Content-Type":"text/html"}); res.end("接收到的图片:</br><img src=‘/show/‘>"); }); // res.writeHead(200, {"Content-Type": "text/plain"}); // res.end("You‘ve sent: " + querystring.parse(postData).text);//使用querystring模块获取上传数据中的文本信息 };
exports.show = (res)=>{//从文件中读取数据并显示到页面 console.log(‘在页面中显示上传数据的请求已被调用‘); fs.readFile("/img/test.png","binary",(err,file)=>{ if(err){ res.writeHead(500,{"Content-Type":"text/plain"}); res.end(err+‘\n‘); }else { res.writeHead(200,{"Content-Type":"image/png"}); res.write(file,"binary"); res.end(); } }); };
即对应的处理程序做对应的事情
步骤三:在server文件中,引入url模块用于解析地址,获取当前路径,
const url = require(‘url‘);
接着创建一个对外提供的start方法,并接收两个参数,route和handle,分别用于处理请求路由和路由对象,在该文件中我们还通过url模块提供的parse().pathname获取到了路径地址,然后调用参数传进来的请求路由方法,并传入路由对象、当前路径、接收到的请求req、响应浏览器的res,最后监听端口
exports.start = (route,handle)=>{ require(‘http‘).createServer((req,res)=>{ const pathname = url.parse(req.url).pathname;//获取当前路径 route(handle,pathname,res,req); console.log(‘路径名称:‘+pathname); }).listen(8888);//监听8888端口 };
步骤四:在router文件中,我们定义一个函数用于该模块提供对外的接口,该函数接收四个参数,路由对象、当前路径、接收到的请求req、响应浏览器的res,在函数中判断当前路径在路由对象中是否存在该函数,如果存在则调用该方法,并传入接收到的请求req、响应浏览器的res两个参数,否则告诉浏览404,页面未找到
exports.route = (handle,pathname,res,req)=>{ console.log("路径名称 " + pathname); if(typeof handle[pathname] === ‘function‘){//匹配是否有这个请求处理程序 return handle[pathname](res,req); }else{ console.log("No request handler found for " + pathname); res.writeHead(404, {"Content-Type": "text/plain"}); res.end("404 Not found"); } };
总体思路:
要把服务器、路由、请求处理程序分开,最后用index.js文件全部连在一起;
①首先创建单独的服务器处理模块,在模块里面创建一个服务器,并通过请求参数和url模块获取到当前的路径,接着调用一个路径处理函数,这个函数传四个参数,第一个参数是从index.js传入的请求处理函数的一个集合对象,第二个参数是当前路径,第三个参数是req,第四个参数是res,最后监听端口,并将这些代码作为一个函数对外开放以方便index.js引入,并且该函数接受两个参数,第一个参数是路径处理函数,第二个参数是请求处理程序函数的对象,服务器模块完成;
②然后创建路径处理模块,该模块将作为一个函数对外开放,函数接收四个参数,第一个参数是从服务器模块传入的请求处理函数的一个集合对象,第二个参数是从服务器模块传入的路径,第三个参数是req,第四个参数是res,然后进行if判断,将从服务器模块传入的路径作为请求处理函数的一个集合对象的参数,判断是否是function,如果是则调用该请求处理程序并传入req,res;
③接着创建请求处理程序,该模块创建不同的对外开放函数,函数参数接收req,res,根据需求制定不同的请求处理程序;
④最后创建一个index.js文件,该文件引入服务器模块,路径处理模块,请求处理程序模块,接着创建一个空对象,把希望制定的路由作为对象的参数然后将对应的请求处理程序模块对应的程序赋值给该参数,最后调用服务器模块对外开放的函数,并传入两个参数,第一个参数是路径处理模块对外的函数,和新创建的的请求处理函数的集合对象。
原文地址:https://www.cnblogs.com/Liqian-Front-End-Engineer/p/11287862.html