zl程序教程

您现在的位置是:首页 >  后端

当前栏目

轻松创建nodejs服务器(10):处理上传图片

Nodejs上传服务器 处理 轻松 创建 图片 10
2023-06-13 09:15:37 时间

本节我们将实现,用户上传图片,并将该图片在浏览器中显示出来。

这里我们要用到的外部模块是FelixGeisendörfer开发的node-formidable模块。它对解析上传的文件数据做了很好的抽象。

要安装这个外部模块,需在cmd下执行命令:

复制代码代码如下:

npminstallformidable

如果输出类似的信息就代表安装成功了:
复制代码代码如下:

npminfobuildSuccess:formidable@1.0.14

安装成功后我们用request将其引入即可:
复制代码代码如下:
varformidable=require(“formidable”);

这里该模块做的就是将通过HTTPPOST请求提交的表单,在Node.js中可以被解析。我们要做的就是创建一个新的IncomingForm,它是对提交表单的抽象表示,之后,就可以用它解析request对象,获取表单中需要的数据字段。

本文案例的图片文件存储在/tmp文件夹中。

我们先来解决一个问题:如何才能在浏览器中显示保存在本地硬盘中的文件?

我们使用fs模块来将文件读取到服务器中。

我们来添加/showURL的请求处理程序,该处理程序直接硬编码将文件/tmp/test.png内容展示到浏览器中。当然了,首先需要将该图片保存到这个位置才行。

我们队requestHandlers.js进行一些修改:

复制代码代码如下:
varquerystring=require("querystring"),
 fs=require("fs");
functionstart(response,postData){
 console.log("Requesthandler"start"wascalled.");
 varbody="<html>"+
   "<head>"+
   "<metahttp-equiv="Content-Type""+
   "content="text/html;charset=UTF-8"/>"+
   "</head>"+
   "<body>"+
   "<formaction="/upload"method="post">"+
   "<textareaname="text"rows="20"cols="60"></textarea>"+
   "<inputtype="submit"value="Submittext"/>"+
   "</form>"+
   "</body>"+
   "</html>";
 response.writeHead(200,{"Content-Type":"text/html"});
 response.write(body);
 response.end();
}
functionupload(response,postData){
 console.log("Requesthandler"upload"wascalled.");
 response.writeHead(200,{"Content-Type":"text/plain"});
 response.write("You"vesentthetext:"+querystring.parse(postData).text);
 response.end();
}
functionshow(response,postData){
 console.log("Requesthandler"show"wascalled.");
 fs.readFile("/tmp/test.png","binary",function(error,file){
 if(error){
  response.writeHead(500,{"Content-Type":"text/plain"});
  response.write(error+"\n");
  response.end();
 }else{
  response.writeHead(200,{"Content-Type":"image/png"});
  response.write(file,"binary");
  response.end();
 }
 });
}
exports.start=start;
exports.upload=upload;
exports.show=show;

我们还需要将这新的请求处理程序,添加到index.js中的路由映射表中:

复制代码代码如下:
varserver=require("./server");
varrouter=require("./router");
varrequestHandlers=require("./requestHandlers");
varhandle={}
handle["/"]=requestHandlers.start;
handle["/start"]=requestHandlers.start;
handle["/upload"]=requestHandlers.upload;
handle["/show"]=requestHandlers.show;
server.start(router.route,handle);

重启服务器之后,通过访问http://localhost:8888/show,就可以看到保存在/tmp/test.png的图片了。

好,最后我们要的就是:

在/start表单中添加一个文件上传元素

将node-formidable整合到我们的upload请求处理程序中,用于将上传的图片保存到/tmp/test.png

将上传的图片内嵌到/uploadURL输出的HTML中

第一项很简单。只需要在HTML表单中,添加一个multipart/form-data的编码类型,移除此前的文本区,添加一个文件上传组件,并将提交按钮的文案改为“Uploadfile”即可。如下requestHandler.js所示:

复制代码代码如下:
varquerystring=require("querystring"),
 fs=require("fs");
functionstart(response,postData){
 console.log("Requesthandler"start"wascalled.");
 varbody="<html>"+
   "<head>"+
   "<metahttp-equiv="Content-Type""+
   "content="text/html;charset=UTF-8"/>"+
   "</head>"+
   "<body>"+
   "<formaction="/upload"enctype="multipart/form-data""+
   "method="post">"+
   "<inputtype="file"name="upload">"+
   "<inputtype="submit"value="Uploadfile"/>"+
   "</form>"+
   "</body>"+
   "</html>";
 response.writeHead(200,{"Content-Type":"text/html"});
 response.write(body);
 response.end();
}
functionupload(response,postData){
 console.log("Requesthandler"upload"wascalled.");
 response.writeHead(200,{"Content-Type":"text/plain"});
 response.write("You"vesentthetext:"+querystring.parse(postData).text);
 response.end();
}
functionshow(response,postData){
 console.log("Requesthandler"show"wascalled.");
 fs.readFile("/tmp/test.png","binary",function(error,file){
 if(error){
  response.writeHead(500,{"Content-Type":"text/plain"});
  response.write(error+"\n");
  response.end();
 }else{
  response.writeHead(200,{"Content-Type":"image/png"});
  response.write(file,"binary");
  response.end();
 }
 });
}
exports.start=start;
exports.upload=upload;
exports.show=show;

接下来,我们要完成第二步,我们从server.js开始——移除对postData的处理以及request.setEncoding(这部分node-formidable自身会处理),转而采用将request对象传递给请求路由的方式:

复制代码代码如下:
varhttp=require("http");
varurl=require("url");
functionstart(route,handle){
 functiononRequest(request,response){
 varpathname=url.parse(request.url).pathname;
 console.log("Requestfor"+pathname+"received.");
 route(handle,pathname,response,request);
 }
 http.createServer(onRequest).listen(8888);
 console.log("Serverhasstarted.");
}
exports.start=start;

接下来修改router.js,这次要传递request对象:

复制代码代码如下:
functionroute(handle,pathname,response,request){
 console.log("Abouttoroutearequestfor"+pathname);
 if(typeofhandle[pathname]==="function"){
 handle[pathname](response,request);
 }else{
 console.log("Norequesthandlerfoundfor"+pathname);
 response.writeHead(404,{"Content-Type":"text/html"});
 response.write("404Notfound");
 response.end();
 }
}
exports.route=route;

现在,request对象就可以在我们的upload请求处理程序中使用了。node-formidable会处理将上传的文件保存到本地/tmp目录中,而我们需

要做的是确保该文件保存成/tmp/test.png。

接下来,我们把处理文件上传以及重命名的操作放到一起,如下requestHandlers.js所示:

复制代码代码如下:
varquerystring=require("querystring"),
 fs=require("fs"),
 formidable=require("formidable");
functionstart(response){
 console.log("Requesthandler"start"wascalled.");
 varbody="<html>"+
   "<head>"+
   "<metahttp-equiv="Content-Type"content="text/html;"+
   "charset=UTF-8"/>"+
   "</head>"+
   "<body>"+
   "<formaction="/upload"enctype="multipart/form-data""+
   "method="post">"+
   "<inputtype="file"name="upload"multiple="multiple">"+
   "<inputtype="submit"value="Uploadfile"/>"+
   "</form>"+
   "</body>"+
   "</html>";
 response.writeHead(200,{"Content-Type":"text/html"});
 response.write(body);
 response.end();
}
functionupload(response,request){
 console.log("Requesthandler"upload"wascalled.");
 varform=newformidable.IncomingForm();
 console.log("abouttoparse");
 form.parse(request,function(error,fields,files){
 console.log("parsingdone");
 fs.renameSync(files.upload.path,"/tmp/test.png");
 response.writeHead(200,{"Content-Type":"text/html"});
 response.write("receivedimage:<br/>");
 response.write("<imgsrc="/show"/>");
 response.end();
 });
}
functionshow(response){
 console.log("Requesthandler"show"wascalled.");
 fs.readFile("/tmp/test.png","binary",function(error,file){
 if(error){
  response.writeHead(500,{"Content-Type":"text/plain"});
  response.write(error+"\n");
  response.end();
 }else{
  response.writeHead(200,{"Content-Type":"image/png"});
  response.write(file,"binary");
  response.end();
 }
 });
}
exports.start=start;
exports.upload=upload;
exports.show=show;

做到这里,我们的服务器就全部完成了。

在执行图片上传的过程中,有的人可能会遇到这样的问题:

照成这个问题的原因我猜测是由于磁盘分区导致的,要解决这个问题就需要改变formidable的默认零时文件夹路径,保证和目标目录处于同一个磁盘分区。

我们找到requestHandlers.js的upload函数,将它做一些修改:

复制代码代码如下:
functionupload(response,request){
 console.log("Requesthandler"upload"wascalled.");
 varform=newformidable.IncomingForm();
 console.log("abouttoparse");
 
 form.uploadDir="tmp";
 
 form.parse(request,function(error,fields,files){
 console.log("parsingdone");
 fs.renameSync(files.upload.path,"/tmp/test.png");
 response.writeHead(200,{"Content-Type":"text/html"});
 response.write("receivedimage:<br/>");
 response.write("<imgsrc="/show"/>");
 response.end();
 });
}

我们增加了一句form.uploadDir=“tmp”,现在重启服务器,再执行上传操作,问题完美解决。