您的位置:首页 > Web前端 > Node.js

文件问题折腾:利用Node.js+express框实现图片上传

2013-05-08 19:00 471 查看
发一下牢骚和主题无关:

    在发开自己的博客引擎的中程过,碰到的第一个问题就是如何现实图片的上传。

    如果对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框现实图片上传
 

文章结束给大家分享下程序员的一些笑话语录: 问答

Q:你是怎么区分一个内向的程序员和一个外向的程序员的? A:外向的程序员会看着你的鞋和你说话时。

Q:为什么程序员不能区分万圣节和圣诞节? A:这是因为 Oct 31 == Dec 25!(八进制的 31==十进制的 25)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐