轻松创建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分页类代码分享
Jun 17 NodeJs
Windows系统下使用Sublime搭建nodejs环境
Apr 13 NodeJs
nodejs创建web服务器之hello world程序
Aug 20 NodeJs
浅谈Nodejs应用主文件index.js
Aug 28 NodeJs
nodejs入门教程一:概念与用法简介
Apr 24 NodeJs
NodeJS实现自定义流的方法
Aug 01 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
详解nodejs 配置文件处理方案
Jan 02 NodeJs
nodejs使用socket5进行代理请求的实现
Feb 21 NodeJs
nodejs如何在package.json中设置多条启动命令
Mar 16 NodeJs
Nodejs实现微信分账的示例代码
Jan 19 NodeJs
浅谈JS和Nodejs中的事件驱动
May 05 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
PHP中Session的概念
2006/10/09 PHP
分享PHP入门的学习方法
2007/01/02 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
PHP redis实现超迷你全文检索
2017/03/04 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
JavaScript asp.net 获取当前超链接中的文本
2009/04/14 Javascript
简单的前端js+ajax 购物车框架(入门篇)
2011/10/29 Javascript
在每个匹配元素的外部插入新元素的方法
2013/12/20 Javascript
ECMAScript6函数默认参数
2015/06/12 Javascript
kindeditor编辑器点中图片滚动条往上顶的bug
2015/07/05 Javascript
基于jquery animate操作css样式属性小结
2015/11/27 Javascript
javascript运算符语法全面概述
2016/07/14 Javascript
jQuery实现倒计时(倒计时年月日可自己输入)
2016/12/02 Javascript
详解angular中如何监控dom渲染完毕
2017/01/03 Javascript
jQuery解析返回的xml和json方法详解
2017/01/05 Javascript
微信小程序 设置启动页面的两种方法
2017/03/09 Javascript
Vue异步组件使用详解
2017/04/08 Javascript
详解Angular CLI + Electron 开发环境搭建
2017/07/20 Javascript
jquery 输入框查找关键字并提亮颜色的实例代码
2018/01/23 jQuery
vue + vuex todolist的实现示例代码
2018/03/09 Javascript
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
2018/05/15 NodeJs
jQuery+vue.js实现的多选下拉列表功能示例
2019/01/15 jQuery
jQuery AJAX与jQuery事件的分析讲解
2019/02/18 jQuery
使用 UniApp 实现小程序的微信登录功能
2020/06/09 Javascript
[07:52]2014DOTA2 TI逗比武士游V社解说背后的故事
2014/07/10 DOTA
python 类详解及简单实例
2017/03/24 Python
解决python3 requests headers参数不能有中文的问题
2019/08/21 Python
PyTorch在Windows环境搭建的方法步骤
2020/05/12 Python
python 日志模块logging的使用场景及示例
2021/01/04 Python
css3学习心得分享
2013/08/19 HTML / CSS
CSS3实现莲花绽放的动画效果
2020/11/06 HTML / CSS
俄罗斯汽车零件和配件在线商店:CarvilleShop
2019/11/29 全球购物
性能测试工程师的面试题
2015/02/20 面试题
中式结婚主持词
2014/03/14 职场文书
小班幼儿评语大全
2014/04/30 职场文书
2016年小学“我们的节日·中秋节”活动总结
2016/04/05 职场文书