您的位置:首页 > 编程语言 > PHP开发

php实现文件上传进度条

2011-08-19 18:06 1196 查看
在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+Ajax带进度条文件上传</title>

<head>

<style type="text/css">

#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="display:none" name="ifm"></iframe>

<form enctype="multipart/form-data" method="POST" action="upload.php" target="ifm" name="myform">

<input type="hidden" name="APC_UPLOAD_PROGRESS" id="remark" >

<input type="file" name="upfile"/>

<input type="submit" value="上传" name="sub"/>

</form>

<div id="progress" class="before"><span id="pecent"></span></div>

<script type="text/javascript">

(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'+type+listener] = listener;

node[type+listener] = function(){node['e'+type+listener]( window.event );}

node.attachEvent( 'on'+type, node[type+listener] );

return true;

}

// Didn't have either so return false

return false;

};

var submit=document.forms["myform"];

addEvent(submit,'submit',startUpload);

var begin;

var request;

var rdm;

var pec=document.getElementById("pecent");

function startUpload()

{

rdm=Math.floor(Math.random()*100000000);

document.getElementById('remark').setAttribute('value',rdm);

document.getElementById("progress").style['display']='block';

//creatXmlHttpRequest();

begin=setTimeout(doRequest,1000);

};

function creatXmlHttpRequest()

{

if(window.ActiveXObject)

{request=new ActiveXObject("Microsoft.XMLHTTP")}

else{request=new XMLHttpRequest();}

};

var count=0;

function doRequest()

{

if(window.ActiveXObject)

{request=new ActiveXObject("Microsoft.XMLHTTP");}

else{request=new XMLHttpRequest();}

if(request!=null){

request.onreadystatechange=handle;

request.open("GET","upload.php?key="+rdm+"&sim=" + (++count),true);

request.send();

}

};

function handle()

{

if(request.readyState==4&&request.status==200)

{

//接受服务器数据

var prgs=eval("(" + request.responseText + ")");

//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()+"%";

if(100==pecentIs)

{

pec.style['width']="200px";

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下无法执行,在火狐下可以运行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: