在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>
- 02.<title>PHP+Ajax带进度条文件上传</title>
- 03.<head>
- 04.<style type="text/css">
- 05.#progress{
- 06.border:2px red solid;
- 07.width:200px;
- 08.height:20px;
- 09.display:none;
- 10.}
- 11.
- 12.#pecent{
- 13.background-color:green;
- 14.display:block;
- 15.width:0px;
- 16.height:20px;
- 17.color:yellow;
- 18.}
- 19.</style>
- 20.</head>
- 21.<body>
- 22. <iframe style="display:none" name="ifm"></iframe>
- 23. <form enctype="multipart/form-data" method="POST" action="upload.php" target="ifm" name="myform">
- 24. <input type="hidden" name="APC_UPLOAD_PROGRESS" id="remark" >
- 25. <input type="file" name="upfile"/>
- 26. <input type="submit" value="上传" name="sub"/>
- 27. </form>
- 28. <div id="progress" class="before"><span id="pecent"></span></div>
- 29.
- 30.<script type="text/javascript">
- 31.(function(){
- 32. function addEvent( node, type, listener ) {
- 33. if (node.addEventListener) {
- 34. // W3C method
- 35. node.addEventListener( type, listener, false );
- 36. return true;
- 37. } else if(node.attachEvent) {
- 38. // MSIE method
- 39. node['e'+type+listener] = listener;
- 40. node[type+listener] = function(){node['e'+type+listener]( window.event );}
- 41. node.attachEvent( 'on'+type, node[type+listener] );
- 42. return true;
- 43. }
- 44. // Didn't have either so return false
- 45. return false;
- 46. };
- 47. var submit=document.forms["myform"];
- 48. addEvent(submit,'submit',startUpload);
- 49. var begin;
- 50. var request;
- 51. var rdm;
- 52. var pec=document.getElementById("pecent");
- 53. function startUpload()
- 54. {
- 55. rdm=Math.floor(Math.random()*100000000);
- 56. document.getElementById('remark').setAttribute('value',rdm);
- 57. document.getElementById("progress").style['display']='block';
- 58. //creatXmlHttpRequest();
- 59. begin=setTimeout(doRequest,1000);
- 60. };
- 61. function creatXmlHttpRequest()
- 62. {
- 63. if(window.ActiveXObject)
- 64. {request=new ActiveXObject("Microsoft.XMLHTTP")}
- 65. else{request=new XMLHttpRequest();}
- 66. };
- 67. var count=0;
- 68. function doRequest()
- 69. {
- 70. if(window.ActiveXObject)
- 71. {request=new ActiveXObject("Microsoft.XMLHTTP");}
- 72. else{request=new XMLHttpRequest();}
- 73.
- 74. if(request!=null){
- 75. request.onreadystatechange=handle;
- 76. request.open("GET","upload.php?key="+rdm+"&sim=" + (++count),true);
- 77. request.send();
- 78. }
- 79. };
- 80. function handle()
- 81. {
- 82. if(request.readyState==4&&request.status==200)
- 83. {
- 84. //接受服务器数据
- 85. var prgs=eval("(" + request.responseText + ")");
- 86. //var prgs=request.responseText;
- 87. var cur=parseInt(prgs.current);
- 88. var total=parseInt(prgs.total);
- 89. var pecentIs=Math.round(cur/total*100);
- 90. pec.innerHTML=pecentIs.toString()+"%";
- 91. if(100==pecentIs)
- 92. {
- 93. pec.style['width']="200px";
- 94. clearTimeout(begin);
- 95. }else{
- 96. begin=setTimeout(doRequest,1000);
- 97. //alert(pecentIs);
- 98. pec.style['width']=pecentIs*2;
- 99. }
- 100. }
- 101. };
- 102. })();
- 103. </script>
- 104. </body>
- 105.</html>
复制代码 2后台upload.php文件代码:- <?php
- 02./*
- 03. * Created on 2010-4-16
- 04. *
- 05. * To change the template for this generated file go to
- 06. * Window - Preferences - PHPeclipse - PHP - Code Templates
- 07. */
- 08. if ($_SERVER['REQUEST_METHOD'] == 'POST'){
- 09.$myfile=$_FILES['upfile'];
- 10.echo $myfile['size'];
- 11.echo $myfile['size'];
- 12.print_r($myfile);
- 13.$tempf=$myfile['tmp_name'];
- 14.$name=$myfile['name'];
- 15.move_uploaded_file($tempf,'up/'.$name);}
- 16.
- 17.if(isset($_GET['key']))
- 18.{
- 19. //header('Content-Type:application/json; charset=utf-8' ) ;
- 20. // Retrieve the status using the getStatus() function below
- 21. //echo json_encode(getStatusAPC());
- 22. echo json_encode(getStatusAPC());
- 23.}
- 24.function getStatusAPC()
- 25.{
- 26. $response=false;
- 27. if($status = apc_fetch('upload_'.$_GET['key'])) {
- 28.
- 29. $response=apc_fetch('upload_'.$_GET['key']);
- 30.
- 31. }
- 32. return $response;
- 33.}
- 34.
- 35.?>
复制代码 问题总结:1,使用setTimeout嵌套和setInterval有区别,用前者效果较好,用后者的话由于请求和返回的时间比较随机,时间间隔把握不好的话,程序会比较混乱,结果往往不正确。 2.发送Ajax请求时每次都要重新实例化xmlhttprequest对象而不能用上次实例化的,否则程序在ie下无法执行,在火狐下可以运行
|