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+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 = function(){node['e'+type+listener]( window.event );}
[*] node.attachEvent( 'on'+type, node );
[*] 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下无法执行,在火狐下可以运行
页:
[1]