wolong 发表于 2015-8-29 01:57:17

php实现文件上传进度条

  
  在PHP5.4以前, 我们可以通过APC提供的功能来实现. 或者使用PECL扩展uploadprogress来实现.
  虽然说, 它们能很好的解决现在的问题, 但是也有很明显的不足:

[*]1. 他们都需要额外安装(我们并没有打算把APC加入PHP5.4)
[*]2. 它们都使用本地机制来存储这些信息, APC使用共享内存, 而uploadprogress使用文件系统(不考虑NFS), 这在多台前端机的时候会造成麻烦.

  

  

  程序需要php的apc模块的支持,关键点就是在上传的form里添加一个hidden的inpu标签,里面要有name为
  APC_UPLOAD_PROGRESS的属性,value值为一个随机数一遍多个人上传。
  
  apc模块的安装方法是,下载php_apc.dll放到ext文件夹下,在php.ini文件里添加
  upload_max_filesize =100M
      apc.rfc1867 = on
      apc.max_file_size = 100M
  extension=php_apc.dll
  然后测试配置是否成功:
if(apc_fetch)
  {echo "apc is working"}
  else{echo "apc is not supported!";}
  
  
  
  运行效果截图

  下面是源码
  1 前台页面:



Html代码
[*]<html>
[*]<title>PHP&#43;Ajax带进度条文件上传</title>
[*]<head>
[*]<style type=&quot;text/css&quot;>
[*]#progress{
[*]border:2px red solid;
[*]width:200px;
[*]height:20px;
[*]display:none;
[*]}
[*]
[*]#pecent{
[*]background-color:green;
[*]display:block;
[*]width:0px;
[*]height:20px;
[*]color:yellow;
[*]}
[*]</style>
[*]</head>
[*]<body>
[*]    <iframe style=&quot;display:none&quot; name=&quot;ifm&quot;></iframe>
[*]      <form enctype=&quot;multipart/form-data&quot; method=&quot;POST&quot; action=&quot;upload.php&quot; target=&quot;ifm&quot; name=&quot;myform&quot;>
[*]      <input type=&quot;hidden&quot; name=&quot;APC_UPLOAD_PROGRESS&quot; id=&quot;remark&quot; >
[*]      <input type=&quot;file&quot; name=&quot;upfile&quot;/>
[*]      <input type=&quot;submit&quot; value=&quot;上传&quot; name=&quot;sub&quot;/>
[*]      </form>
[*]      <div id=&quot;progress&quot; class=&quot;before&quot;><span id=&quot;pecent&quot;></span></div>
[*]
[*]<script type=&quot;text/javascript&quot;>
[*](function(){
[*]    function addEvent( node, type, listener ) {
[*]    if (node.addEventListener) {
[*]      // W3C method
[*]      node.addEventListener( type, listener, false );
[*]      return true;
[*]    } else if(node.attachEvent) {
[*]      // MSIE method
[*]      node['e'&#43;type&#43;listener] = listener;
[*]      node = function(){node['e'&#43;type&#43;listener]( window.event );}
[*]      node.attachEvent( 'on'&#43;type, node );
[*]      return true;
[*]    }
[*]    // Didn't have either so return false
[*]    return false;
[*]    };
[*]    var submit=document.forms[&quot;myform&quot;];
[*]    addEvent(submit,'submit',startUpload);
[*]    var begin;
[*]    var request;
[*]    var rdm;
[*]    var pec=document.getElementById(&quot;pecent&quot;);
[*]    function startUpload()
[*]    {
[*]      rdm=Math.floor(Math.random()*100000000);
[*]      document.getElementById('remark').setAttribute('value',rdm);
[*]      document.getElementById(&quot;progress&quot;).style['display']='block';
[*]      //creatXmlHttpRequest();
[*]      begin=setTimeout(doRequest,1000);
[*]    };
[*]    function creatXmlHttpRequest()
[*]    {
[*]      if(window.ActiveXObject)
[*]      {request=new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;)}
[*]      else{request=new XMLHttpRequest();}
[*]    };
[*]    var count=0;
[*]    function doRequest()
[*]   {
[*]       if(window.ActiveXObject)
[*]      {request=new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);}
[*]      else{request=new XMLHttpRequest();}
[*]
[*]       if(request!=null){
[*]       request.onreadystatechange=handle;
[*]       request.open(&quot;GET&quot;,&quot;upload.php?key=&quot;&#43;rdm&#43;&quot;&sim=&quot; &#43; (&#43;&#43;count),true);
[*]       request.send();
[*]       }
[*]   };
[*]      function handle()
[*]      {
[*]            if(request.readyState==4&&request.status==200)
[*]            {
[*]                //接受服务器数据
[*]                var prgs=eval(&quot;(&quot; &#43;request.responseText &#43; &quot;)&quot;);
[*]                //var prgs=request.responseText;
[*]                var cur=parseInt(prgs.current);
[*]                var total=parseInt(prgs.total);
[*]                var pecentIs=Math.round(cur/total*100);
[*]                pec.innerHTML=pecentIs.toString()&#43;&quot;%&quot;;
[*]                if(100==pecentIs)
[*]                {
[*]                  pec.style['width']=&quot;200px&quot;;
[*]                  clearTimeout(begin);
[*]                }else{
[*]                  begin=setTimeout(doRequest,1000);
[*]                  //alert(pecentIs);
[*]                  pec.style['width']=pecentIs*2;
[*]                }
[*]            }
[*]      };
[*]    })();
[*]    </script>
[*]    </body>
[*]</html>
  
  2后台upload.php文件代码:



Php代码
[*]<?php
[*]/*
[*] * Created on 2010-4-16
[*] *
[*] * To change the template for this generated file go to
[*] * Window - Preferences - PHPeclipse - PHP - Code Templates
[*] */
[*] if ($_SERVER['REQUEST_METHOD'] == 'POST'){
[*]$myfile=$_FILES['upfile'];
[*]echo $myfile['size'];
[*]echo $myfile['size'];
[*]print_r($myfile);
[*]$tempf=$myfile['tmp_name'];
[*]$name=$myfile['name'];
[*]move_uploaded_file($tempf,'up/'.$name);}
[*]
[*]if(isset($_GET['key']))
[*]{
[*]    //header('Content-Type:application/json; charset=utf-8' ) ;
[*]    // Retrieve the status using the getStatus() function below
[*]    //echo json_encode(getStatusAPC());
[*]    echo json_encode(getStatusAPC());
[*]}
[*]function getStatusAPC()
[*]{
[*]    $response=false;
[*]    if($status = apc_fetch('upload_'.$_GET['key'])) {
[*]         
[*]      $response=apc_fetch('upload_'.$_GET['key']);
[*]         
[*]    }
[*]    return $response;
[*]}
[*]
[*]?>
  问题总结:
  1,使用setTimeout嵌套和setInterval有区别,用前者效果较好,用后者的话由于请求和返回的时间比较随机,时间间隔把握不好的话,程序会比较混乱,结果往往不正确。
  2.发送Ajax请求时每次都要重新实例化xmlhttprequest对象而不能用上次实例化的,否则程序在ie下无法执行,在火狐下可以运行
  
页: [1]
查看完整版本: php实现文件上传进度条