轻松创建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的前后端分离的思考与实践(四)安全问题解决方案
Sep 26 NodeJs
NodeJS制作爬虫全过程
Dec 22 NodeJs
nodejs 整合kindEditor实现图片上传
Feb 03 NodeJs
Windows系统下使用Sublime搭建nodejs环境
Apr 13 NodeJs
Nodejs Stream 数据流使用手册
Apr 17 NodeJs
使用nodejs下载风景壁纸
Feb 05 NodeJs
nodejs中向HTTP响应传送进程的输出
Mar 19 NodeJs
NodeJs测试框架Mocha的安装与使用
Mar 28 NodeJs
详解nodejs微信公众号开发——1.接入微信公众号
Apr 10 NodeJs
Nodejs模块载入运行原理
Feb 23 NodeJs
nodejs取得当前执行路径的方法
May 13 NodeJs
CentOS7中源码编译安装NodeJS的完整步骤
Oct 13 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
天津市收音机工业发展史
2021/03/04 无线电
PHP的命令行命令使用指南
2015/08/18 PHP
PHP实现递归无限级分类
2015/10/22 PHP
由浅到深了解JavaScript类
2006/09/08 Javascript
[原创]后缀就扩展名为js的文件是什么文件
2007/12/06 Javascript
鼠标事件延时切换插件
2011/03/12 Javascript
select标签模拟/美化方法采用JS外挂式插件
2013/04/01 Javascript
js兼容的placeholder属性详解
2013/08/18 Javascript
js动态设置div的值下例子
2013/10/29 Javascript
JS读取XML文件示例代码
2013/11/15 Javascript
JS过滤url参数特殊字符的实现方法
2013/12/24 Javascript
HTML页面登录时的JS验证方法
2014/05/28 Javascript
node.js正则表达式获取网页中所有链接的代码实例
2014/06/03 Javascript
jQuery中animate用法实例分析
2015/03/09 Javascript
AngularJS入门教程之ng-class 指令用法
2016/08/01 Javascript
轻松掌握JavaScript策略模式
2016/08/25 Javascript
Weex开发之地图篇的具体使用
2019/10/16 Javascript
python用ConfigObj读写配置文件的实现代码
2013/03/04 Python
Python 递归函数详解及实例
2016/12/27 Python
Python实现的概率分布运算操作示例
2017/08/14 Python
Python装饰器知识点补充
2018/05/28 Python
python3 json数据格式的转换(dumps/loads的使用、dict to str/str to dict、json字符串/字典的相互转换)
2019/04/01 Python
python matplotlib.pyplot.plot()参数用法
2020/04/14 Python
python如何调用php文件中的函数详解
2020/12/29 Python
具有防紫外线功能的高性能钓鱼服装:Hook&Tackle
2018/08/16 全球购物
美国折扣地毯销售网站:Rugs.com
2020/03/27 全球购物
最新计算机专业自荐信
2013/10/16 职场文书
《狐假虎威》教学反思
2014/02/07 职场文书
烹饪自我鉴定
2014/03/01 职场文书
我爱我的祖国演讲稿
2014/05/04 职场文书
我爱读书演讲稿
2014/05/07 职场文书
2015年度招聘工作总结
2015/05/28 职场文书
2016年党课培训学习心得体会
2016/01/07 职场文书
工作计划范文之财务管理
2019/08/09 职场文书
Python中tkinter的用户登录管理的实现
2021/04/22 Python
python pandas 解析(读取、写入)CSV 文件的操作方法
2022/12/24 Python