获取文件上传进度

(迁移至CNODE 原文地址)
国庆节对于一个大三党来说是一整块难得的时间,出去玩也好,做其他的事也好,都可以随心所欲地安排。想着利用这个时间开发 一个社交网站作为学习node的一个总结,不怎么精,也算凑合,无奈还有太多的事儿要做啊。废话不多说,转入正题:

今天遇到图片上传的问题,服务器能成功收到图片信息,但如何将进度返给客户端呢?用 发送文件是一个post请求,服务器只可能回复一次,而且这个回复主要用来回复前端上传 文件的获取地址,不适合再做他用。

网上查了查,说是可以用flash做,好吧,表示不会flash….. 目前主要的问题是如何不断地从服务器获得上传进度,socket貌似能做到这一点,问题是不知道上传结束时客户端如何主动断开socket链接,有知道的朋友麻烦告诉一声^-^,于是决定采用轮询了。
先贴前端部分代码:
html部分

<iframe name="hidden_iframe" id='hidden_iframe' style="display:none" src=""> </iframe>
<form method='post' action='/uploadimage' enctype='multipart/form-data' target="hidden_iframe">
   <input type="text" name="randomID" id="uploadTag" style="display:none" />
   选择图片:<input type='file' name='img' id='filearea' onchange="setTag()"/>
   <input type='submit' value='提交' onclick=" startRequest()" />
</form>
<div id="showbox" ></div>

JS部分

           var uploadTag;
           function startRequest()
           {
                 var json={"randomID":uploadTag};
                setTimeout(post_data(obj,'/getuploadprocess',dealResponse),1000);
           }
           function dealResponse(json)
           {
             var box=document.getElementById("showbox");
             box.innerText=json.progress+'%';
             if(json.progress!=100)
             {
               startRequest();
             }
           }   

//上面这俩个function 组成一个不达目的不罢休的轮询,post_data是个ajax,就不贴了

           function setTag()
           {
               uploadTag=Math.ceil(Math.random()*1000000);
               var tag=document.getElementById("uploadTag");
               tag.value=uploadTag;
           }

//设置随机id,避免搞不清是请求哪个文件的进度

           function uploadErr(message)
           {
              alert(message);
           }

//处理错误,当然这里只是简单alert,没有考虑用户体验,就写简单点吧

           function uploadEnd(json)
           {
             var obj=JSON.parse(json)
             alert(obj.message)
           }

//上传结束的callback,返回图片的获取地址,前端应该将其设置成一个img元素的src属性,也从简了:)
* 后端:*
后端大部分人都是使用的express,然后就顺便设置了app.use(multer(dest:”“))解析请求,那可就做不了进度条了,建议把这个设置删了,然后 var formidable=require(“formidable”);(写在路由模块里);
代码:

           var uploadprogress={};//全局变量,存进度
           module.exports=function(app)
           {
           ...........................................................................
           ...........................................................................
             app.post('/uploadimage',function(req,res){
                 var id=1;
                 var uploadfile;
                 var form=new formidable.IncomingForm();//formidable模块的用法自己去github看文档吧
                 form.uploadDir='';
                 from.keepExtensions=true;
                 form.on("field",function(name,value){//设置唯一可标识的id
                 id=req.session.user._id+req.body.randomID;//这个value就是表单中文本框的值
           });
                 form.on("err",function(err){
                   var callback="<script>top.uploadErr('"+err+"');</script>";
                    res.end(callback);//这段文本发回前端就会被同名的函数执行
           })
                  from.on("progress",function(bytesRecieved,bytesExpected){
                     uploadprogress.id=Math.ceil((bytesRecieved/bytesExpected)*100);//更新进度
                  //这里有个id的值是否已经设置的问题,不过没关系,就算仍是最初的1,也只耗一丁点内存
           })
                  form.on("abort",function(){
                    ............
           })
                  form.on("file",function(err,file){
                      if(err)
                     {
                          console.log(err);
                           var callback="<script>top.uploadErr('"+err+"');</script>";
                           res.end(callback);           
                        }
                     uploadfile=file;//记录文件信息
           })
                 form.on("end",function(){
                     var file=new File()
                     .......
                     ...... 
                    file.save();//将文件信息存入数据库,如果是文章里面的图片的话,就没有必要存了,在前端直接设置src就相当于存了
                    var fpath=uploadfile.path;
                    var callback="<script>top.uploadEnd('"+fpath+"');</script>";
                    res.end(callback);
           })
                 form.parse(req);
           })

           app.post('/getuploadprocess',function(req,res){
                var id=req.session.user._id+req.body.randomID;
                var pr;
                if(uploadprogress.id)
                 {
                   pr=uploadprogress.id;
                 }
                else
               {
                   pr=0;
               }
               if(pr==100)
               {
                  delete uploadprogress.id;
               }
                 res.status(200).json({"progress":pr});
           })
           }

ok主要的代码已经贴完了,下面来说一下工作的流程,首先由表单提交文件,在确定文件后会自动生成一个随机ID用于标识,这个ID发给后台和user的id组合为文件的标识;后台接受文件上传请求,formidable开始解析文件,主要监听progress事件,由其返回的参数来更新上传进度。在表单点击提交的时候同时触发startRequest函数,向后台获取上传进度,这个请求由/getuploadprogress处理,里面的代码就是简单的响应和清理功能。自此全部结束,前端获得进度后想要以什么方式展现就随看官发挥吧,我就简单展现其百分比了

PS:如果有大神路过,小弟请教一个问题:这个代码 是实现了功能,但获得进度是个长轮询,不知道对服务器来讲压力大不大。。测试时我同时上传俩个400多M的文件,电脑风扇就转个不停。虽然文件上传成功了,但还是担心性能问题(我用本机做的服务器),求大神留下高见!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值