折腾:利用Node.js+express框实现图片上传
2013-02-27 23:32
399 查看
在开发自己的博客引擎的过程中,遇到的第一个问题就是如何实现图片的上传。
如果对express中的
但有几个非常常规的功能无法通过这些个参数实现的,比如
如何判断上传成功?
如何显示上传进度?
如何在上传之前限制图片的大小和分辨率?
如何重命名图片并且另取存放路径?
并且解决以上的几个问题靠原生的框架是不够的,于是想到了 Modules,找到了star数比较多的node-formidable,按照tutorial,在
但运行之后,发现所有的事件回调并没有被触发(因为所有handler中的
Google了几篇关于formidable使用的文章。确定我们使用formidable的方式是没有问题的。于是尝试把问题定位到是不是这个组件在整体架构中的问题,比如和express的组件有了冲突?
首先看看是不是express的问题,先从和上传文件相关的
The bodyParser() middleware utilizes the node-formidable module internally, and accepts the same options. An example of this is the keepExtensions formidable option, defaulting to false which in this case gives you the filename "/tmp/8ef9c52abe857867fd0a4e9a819d1876" void of the ".png" extension. To enable this, and others you may pass them to bodyParser():
也就是说,我们在初始化
非常好!但是仍然不够,只有给上传的不同阶段绑定不同的处理函数,这样才能更灵活的控制。
这次去express在github上托管的代码看看,看看在issue中有没有相同问题的人——果然是有的,比如这个 问题:
Is there an event I can listen to to get the progress of an file upload? Apologies for posting this as an issue.
但是express的作者的回答差点让我石化了:
not currently no. modern browsers and moving on in the future the client-side can report progress fine so I feel like the average case wont really need this, maybe even some do now, but that being said you can still disable the multipart support and use formidable directly for the events. Maybe sometime I'll add some event handlers but that wouldn't really be very middleware-like so it would be kinda awkward I think.
他认为现代浏览器在不远的将来就会有报告上传文件进度的功能,所以他反而删除了?但万幸的是他告诉我们如果真的有这个需求的话,可以在禁用multipart这个中间件(middleware)的同时,使用formidable。于是我尝试这么做:
但是没有起任何作用。
继续按图索骥,考虑到multipart应该算作是一个属于connect的中间件,我们来到了multipart的 官方文档,找到了关于它的说明,更关键的说关于初始化时option的说明:
The options passed are merged with formidable's IncomingForm object, allowing you to configure the upload directory, size limits, etc. For example if you wish to change the upload dir do the following.
更关键的是关于它 defer 这个参数的说明:
defer defers processing and exposes the Formidable form object as req.form. next() is called without waiting for the form's "end" event. This option is useful if you need to bind to the "progress" event, for example.
一切豁然开朗了!只要开启defer这个参数,就可以开启关于各种上传事件的绑定。不多说了,展示完整的代码吧:
所有的事件列表和事件的参数列表都可以参照 node-formidable 的文档,在这里就不多赘述了。
最后回答文章开头的那几个问题:
问:如何限制图片大小
问:如何显示上传进度
问:如何修改文件名
本文同时也发布在我的个人博客qingbob
折腾:利用Node.js+express框实现图片上传
如果对express中的
app.post('/', function (req, res))方法熟悉的话,方法中的
req.files已经代表的是上传的文件,打印出来之后可以看到文件的一系列属性,比如说通过上传的路由,重命名之后的名称,存放的路径,文件的大小等等:
{ size:74643, path:'/tmp/8ef9c52abe857867fd0a4e9a819d1876', name:'edge.png', type:'image/png', hash:false, lastModifiedDate:ThuAug09201220:07:51 GMT-0700(PDT), _writeStream:{ path:'/tmp/8ef9c52abe857867fd0a4e9a819d1876', fd:13, writable:false, flags:'w', encoding:'binary', mode:438, bytesWritten:74643, busy:false, _queue:[], _open:[Function], drainable:true}, length:[Getter], filename:[Getter], mime:[Getter]}}
但有几个非常常规的功能无法通过这些个参数实现的,比如
如何判断上传成功?
如何显示上传进度?
如何在上传之前限制图片的大小和分辨率?
如何重命名图片并且另取存放路径?
并且解决以上的几个问题靠原生的框架是不够的,于是想到了 Modules,找到了star数比较多的node-formidable,按照tutorial,在
app.post中的贴上了示例代码:
var formidable =require('formidable'); app.post('/upload',function(req, res){var form =new formidable.IncomingForm({ form.keepExtensions =false;//keep .jpg/.png form.uploadDir ="upload/";//upload path}); form.parse(req,function(err, fields, files){ console.log("parse!");});//bind event handler form.on("progress",function(err){}) form.on("complete",function(err){})})
但运行之后,发现所有的事件回调并没有被触发(因为所有handler中的
console.log都没有被打印出来)。 可图片却正常上传了! ,或许是 我们使用formidable的方式不对,忽略了什么吧。
Google了几篇关于formidable使用的文章。确定我们使用formidable的方式是没有问题的。于是尝试把问题定位到是不是这个组件在整体架构中的问题,比如和express的组件有了冲突?
首先看看是不是express的问题,先从和上传文件相关的
req.files入手。果然,在关于
req.files的 API 中看到,其实
bodyParser()和
node-formidable模块其实早已经被整合在一起,甚至参数都已经可以通用:
The bodyParser() middleware utilizes the node-formidable module internally, and accepts the same options. An example of this is the keepExtensions formidable option, defaulting to false which in this case gives you the filename "/tmp/8ef9c52abe857867fd0a4e9a819d1876" void of the ".png" extension. To enable this, and others you may pass them to bodyParser():
也就是说,我们在初始化
bodyParser()的时候就可以设置有关上传的一些参数了,比如可以限制上传文件的大小,改变上传路径,自动重命名后保留文件后缀
app.use(express.bodyParser({ uploadDir:"media/upload/", keepExtensions:true, limit:10000000}));
非常好!但是仍然不够,只有给上传的不同阶段绑定不同的处理函数,这样才能更灵活的控制。
这次去express在github上托管的代码看看,看看在issue中有没有相同问题的人——果然是有的,比如这个 问题:
Is there an event I can listen to to get the progress of an file upload? Apologies for posting this as an issue.
但是express的作者的回答差点让我石化了:
not currently no. modern browsers and moving on in the future the client-side can report progress fine so I feel like the average case wont really need this, maybe even some do now, but that being said you can still disable the multipart support and use formidable directly for the events. Maybe sometime I'll add some event handlers but that wouldn't really be very middleware-like so it would be kinda awkward I think.
他认为现代浏览器在不远的将来就会有报告上传文件进度的功能,所以他反而删除了?但万幸的是他告诉我们如果真的有这个需求的话,可以在禁用multipart这个中间件(middleware)的同时,使用formidable。于是我尝试这么做:
app.disable("multipart");
但是没有起任何作用。
继续按图索骥,考虑到multipart应该算作是一个属于connect的中间件,我们来到了multipart的 官方文档,找到了关于它的说明,更关键的说关于初始化时option的说明:
The options passed are merged with formidable's IncomingForm object, allowing you to configure the upload directory, size limits, etc. For example if you wish to change the upload dir do the following.
更关键的是关于它 defer 这个参数的说明:
defer defers processing and exposes the Formidable form object as req.form. next() is called without waiting for the form's "end" event. This option is useful if you need to bind to the "progress" event, for example.
一切豁然开朗了!只要开启defer这个参数,就可以开启关于各种上传事件的绑定。不多说了,展示完整的代码吧:
app.configure(function(){ app.use(express.bodyParser({ keepExtensions:true, limit:10000000,// 10M limit defer:true//enable event }));}) app.post('/upload',function(req, res){//bind event handler req.form.on('progress',function(bytesReceived, bytesExpected){}); req.form.on('end',function(){ console.log(req.files); res.send("done");});})
所有的事件列表和事件的参数列表都可以参照 node-formidable 的文档,在这里就不多赘述了。
最后回答文章开头的那几个问题:
问:如何限制图片大小
if(req.files.image.size >307200)// 300 * 1024{ msg +='File size no accepted. Max: 300k; }
问:如何显示上传进度
req.form.on('progress',function(bytesReceived, bytesExpected){ console.log(((bytesReceived / bytesExpected)*100)+"% uploaded");});
问:如何修改文件名
var fs =require('fs'); fs.renameSync(req.files.image.path,'public/files/img'+ new_name);
本文同时也发布在我的个人博客qingbob
折腾:利用Node.js+express框实现图片上传
相关文章推荐
- 文件问题折腾:利用Node.js+express框实现图片上传
- 利用WCF与Android实现图片上传并传参
- 利用FormData实现附件上传(实现上传图片显示)
- Mvc利用淘宝Kissy uploader实现图片批量上传附带瀑布流的照片墙
- 利用KindEditor的uploadbutton实现异步上传图片
- [置顶] 在HTML表单中利用JavaScript实现图片上传的前端校验
- 利用webservices实现图片远程上传
- 完美实现 IE10 下利用HTML5实现文件上传(图片上传)功能
- 利用iframe+php实现图片的上传
- 利用OKHttp实现 图片上传 ---b509小贴士
- 利用formdata实现一个input 上传类型 上传多个图片
- 利用HTML5的新特点实现图片文件异步上传
- 利用zend framework的Zend_File_Transfer_Adapter_Http类实现多个图片的上传
- iPhone开发笔记(12)利用.net实现服务端接收上传的图片并保存
- 利用SpringMVC原生封装的对象实现图片上传及图片回显功能的实现及案例代码
- 利用ASPUPLOAD,ASPJPEG实现图片上传自动生成缩略图及加上水印
- Mvc利用淘宝Kissy uploader实现图片批量上传附带瀑布流的照片墙
- 移动端利用H5实现压缩图片上传功能
- 利用ajaxfileupload.js实现跨域上传图片并处理返回的数据
- vue利用type=file 实现本地上传图片