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


Posted in NodeJs onDecember 18, 2014

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

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

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

npm install formidable

如果输出类似的信息就代表安装成功了:
npm info build Success: formidable@1.0.14

安装成功后我们用request将其引入即可:
var formidable = require(“formidable”);

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

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

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

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

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

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

var querystring = require("querystring"),

 fs = require("fs");

function start(response, postData) {

 console.log("Request handler 'start' was called.");

 var body = '<html>'+

    '<head>'+

    '<meta http-equiv="Content-Type" '+

    'content="text/html; charset=UTF-8" />'+

    '</head>'+

    '<body>'+

    '<form action="/upload" method="post">'+

    '<textarea name="text" rows="20" cols="60"></textarea>'+

    '<input type="submit" value="Submit text" />'+

    '</form>'+

    '</body>'+

    '</html>';

 response.writeHead(200, {"Content-Type": "text/html"});

 response.write(body);

 response.end();

}

function upload(response, postData) {

 console.log("Request handler 'upload' was called.");

 response.writeHead(200, {"Content-Type": "text/plain"});

 response.write("You've sent the text: "+ querystring.parse(postData).text);

 response.end();

}

function show(response, postData) {

 console.log("Request handler 'show' was called.");

 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中的路由映射表中:

var server = require("./server");

var router = require("./router");

var requestHandlers = require("./requestHandlers");

var handle = {}

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的编码类型,移除此前的文本区,添加一个文件上传组件,并将提交按钮的文案改为“Upload file”即可。 如下requestHandler.js所示:

var querystring = require("querystring"),

 fs = require("fs");

function start(response, postData) {

 console.log("Request handler 'start' was called.");

 var 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="Upload file" />'+

    '</form>'+

    '</body>'+

    '</html>';

 response.writeHead(200, {"Content-Type": "text/html"});

 response.write(body);

 response.end();

}

function upload(response, postData) {

 console.log("Request handler 'upload' was called.");

 response.writeHead(200, {"Content-Type": "text/plain"});

 response.write("You've sent the text: "+ querystring.parse(postData).text);

 response.end();

}

function show(response, postData) {

 console.log("Request handler 'show' was called.");

 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对象传递给请求路由的方式:

var http = require("http");

var url = require("url");

function start(route, handle) {

 function onRequest(request, response) {

  var pathname = url.parse(request.url).pathname;

  console.log("Request for " + pathname + " received.");

  route(handle, pathname, response, request);

 }

 http.createServer(onRequest).listen(8888);

 console.log("Server has started.");

}

exports.start = start;

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

function route(handle, pathname, response, request) {

 console.log("About to route a request for " + pathname);

 if (typeof handle[pathname] === 'function') {

  handle[pathname](response, request);

 } else {

  console.log("No request handler found for " + pathname);

  response.writeHead(404, {"Content-Type": "text/html"});

  response.write("404 Not found");

  response.end();

 }

}

exports.route = route;

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

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

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

var querystring = require("querystring"),

 fs = require("fs"),

 formidable = require("formidable");

function start(response) {

 console.log("Request handler 'start' was called.");

 var 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" multiple="multiple">'+

    '<input type="submit" value="Upload file" />'+

    '</form>'+

    '</body>'+

    '</html>';

 response.writeHead(200, {"Content-Type": "text/html"});

 response.write(body);

 response.end();

}

function upload(response, request) {

 console.log("Request handler 'upload' was called.");

 var form = new formidable.IncomingForm();

 console.log("about to parse");

 form.parse(request, function(error, fields, files) {

  console.log("parsing done");

  fs.renameSync(files.upload.path, "/tmp/test.png");

  response.writeHead(200, {"Content-Type": "text/html"});

  response.write("received image:<br/>");

  response.write("<img src='/show' />");

  response.end();

 });

}

function show(response) {

 console.log("Request handler 'show' was called.");

 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;

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

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

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

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

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

function upload(response, request) { 

 console.log("Request handler 'upload' was called."); 

 var form = new formidable.IncomingForm(); 

 console.log("about to parse");

 

 form.uploadDir = "tmp";

 

 form.parse(request, function(error, fields, files) { 

  console.log("parsing done"); 

  fs.renameSync(files.upload.path, "/tmp/test.png"); 

  response.writeHead(200, {"Content-Type": "text/html"}); 

  response.write("received image:<br/>"); 

  response.write("<img src='/show' />"); 

  response.end(); 

 }); 

}

我们增加了一句 form.uploadDir = “tmp”,现在重启服务器,再执行上传操作,问题完美解决。
NodeJs 相关文章推荐
跟我学Nodejs(三)--- Node.js模块
May 25 NodeJs
nodejs URL模块操作URL相关方法介绍
Mar 03 NodeJs
nodejs实现遍历文件夹并统计文件大小
May 28 NodeJs
NodeJs读取JSON文件格式化时的注意事项
Sep 25 NodeJs
nodejs multer实现文件上传与下载
May 10 NodeJs
mac下的nodejs环境安装的步骤
May 24 NodeJs
深入解析nodejs HTTP服务
Jul 25 NodeJs
nodejs取得当前执行路径的方法
May 13 NodeJs
nodejs读取本地中文json文件出现乱码解决方法
Oct 10 NodeJs
NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法
Oct 17 NodeJs
NodeJs之word文件生成与解析的实现代码
Apr 01 NodeJs
nodejs 递归拷贝、读取目录下所有文件和目录
Jul 18 NodeJs
轻松创建nodejs服务器(10):处理POST请求
Dec 18 #NodeJs
轻松创建nodejs服务器(7):阻塞操作的实现
Dec 18 #NodeJs
轻松创建nodejs服务器(8):非阻塞是如何实现的
Dec 18 #NodeJs
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 #NodeJs
轻松创建nodejs服务器(6):作出响应
Dec 18 #NodeJs
轻松创建nodejs服务器(5):事件处理程序
Dec 18 #NodeJs
轻松创建nodejs服务器(4):路由
Dec 18 #NodeJs
You might like
非常不错的MySQL优化的8条经验
2008/03/24 PHP
PHPMailer安装方法及简单实例
2008/11/25 PHP
php数组函数序列之array_flip() 将数组键名与值对调
2011/11/07 PHP
PHP实现懒加载的方法
2015/03/07 PHP
thinkphp5.1框架实现格式化mysql时间戳为日期的方式小结
2019/10/10 PHP
jQuery-ui引入后Vs2008的无智能提示问题解决方法
2014/02/10 Javascript
jquery实现翻动fadeIn显示的方法
2015/03/05 Javascript
基于jquery实现一个滚动的分步注册向导-附源码
2015/08/26 Javascript
Vue组件教程之Toast(Vue.extend 方式)详解
2019/01/27 Javascript
nodejs中request库使用HTTPS代理的方法
2019/04/30 NodeJs
node.JS二进制操作模块buffer对象使用方法详解
2020/02/06 Javascript
vue 组件基础知识总结
2021/01/26 Vue.js
[03:38]TI4西雅图DOTA2前线报道 71专访
2014/07/08 DOTA
Python pyinotify模块实现对文档的实时监控功能方法
2018/10/13 Python
python如何爬取网站数据并进行数据可视化
2019/07/08 Python
Python爬虫抓取技术的一些经验
2019/07/12 Python
python项目对接钉钉SDK的实现
2019/07/15 Python
Pycharm+django2.2+python3.6+MySQL实现简单的考试报名系统
2019/09/05 Python
详解Python3迁移接口变化采坑记
2019/10/11 Python
python requests抓取one推送文字和图片代码实例
2019/11/04 Python
python 写函数在一定条件下需要调用自身时的写法说明
2020/06/01 Python
Python异常处理机制结构实例解析
2020/07/23 Python
Python利用socket模块开发简单的端口扫描工具的实现
2021/01/27 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
最便宜促销价格订机票:Airpaz(总部设在印尼,支持中文)
2018/11/13 全球购物
size?丹麦官网:英国伦敦的球鞋精品店
2019/04/15 全球购物
会计助理的岗位职责
2013/11/29 职场文书
主管会计岗位责任制
2014/02/10 职场文书
无偿献血倡议书
2014/04/14 职场文书
工作求职信
2014/07/04 职场文书
信用卡结清证明怎么写
2014/09/13 职场文书
2015年幼儿园中班工作总结
2015/04/25 职场文书
党支部考察鉴定意见
2015/06/02 职场文书
幼儿教师师德培训心得体会
2016/01/09 职场文书
Nginx同一个域名配置多个项目的实现方法
2021/03/31 Servers
Python字符串的转义字符
2022/04/07 Python