使用Javascript和PHP的视频文件上传进度条

时间:2014-02-18 14:11:13

标签: javascript php ajax

我想使用PHP上传视频文件,并通过进度条显示上传的进度。但这比我想象的更困难,我试图把我发现的碎片放在一起,但不幸的是我没有找到一个工作的代码,所有需要的PHP,ajax和HTML代码,所以香港专业教育学院试图把不同的部分放在一起。

我的代码功能几乎完全。唯一的事情是,文件上传的当前进程,我得到的百分比,仅在进程结束后由我的javascript加载,而不是从开头加载。

这是我的PHP代码:

 function file_get_size($file) {
    //open file
    $fh = fopen($file, "r");
    //declare some variables
    $size = "0";
    $char = "";
    //set file pointer to 0; I'm a little bit paranoid, you can remove this
    fseek($fh, 0, SEEK_SET);
    //set multiplicator to zero
    $count = 0;
    while (true) {
        //jump 1 MB forward in file
        fseek($fh, 1048576, SEEK_CUR);
        //check if we actually left the file
        if (($char = fgetc($fh)) !== false) {
            //if not, go on
            $count ++;
        } else {
            //else jump back where we were before leaving and exit loop
            fseek($fh, -1048576, SEEK_CUR);
            break;
        }
    }
    //we could make $count jumps, so the file is at least $count * 1.000001 MB large
    //1048577 because we jump 1 MB and fgetc goes 1 B forward too
    $size = bcmul("1048577", $count);
    //now count the last few bytes; they're always less than 1048576 so it's quite fast
    $fine = 0;
    while(false !== ($char = fgetc($fh))) {
        $fine ++;
    }
    //and add them
    $size = bcadd($size, $fine);
    fclose($fh);
    return $size;
}
$filesize = file_get_size('remote-file');

$remote = fopen('remote-file', 'r');
$local = fopen('local-file', 'w');

$read_bytes = 0;
while(!feof($remote)) {
  $buffer = fread($remote, 2048);
  fwrite($local, $buffer);

  $read_bytes += 2048;

  //Use $filesize as calculated earlier to get the progress percentage
  $progress = min(100, 100 * $read_bytes / $filesize);
  fwrite(fopen('files/upload/progress.txt', 'w'), $progress);

  //you'll need some way to send $progress to the browser.
  //maybe save it to a file and then let an Ajax call check it?
}
fclose($remote);
fclose($local);

这是我的Javascript代码:

function main()
{
    var pathOfFileToRead = "files/upload/progress.txt";

    var contentsOfFileAsString = FileHelper.readStringFromFileAtPath
    (
        pathOfFileToRead
    );

    document.body.innerHTML = contentsOfFileAsString;
}

function FileHelper()
{}
{
    FileHelper.readStringFromFileAtPath = function(pathOfFileToReadFrom)
    {
        var request = new XMLHttpRequest();
        request.open("GET", pathOfFileToReadFrom, false);
        request.send(null);
        var returnValue = request.responseText;

        return returnValue;
    }
}

main();

function progressBarSim(al) {
  var bar = document.getElementById('bar-fill');
  var status = document.getElementById('status');
  status.innerHTML = al+"%";
  bar.value = al;
  al++;
var sim = setTimeout("progressBarSim("+al+")",1000);
if(al == 100){
 status.innerHTML = "100%";
 bar.value = 100;
 clearTimeout(sim);
 var finalMessage = document.getElementById('finalMessage');
 finalMessage.innerHTML = "Process is complete";
}
}
var amountLoaded = 0;
progressBarSim(amountLoaded);

Progressbar目前在Timer上工作,因为main()函数从一开始就不读取“progress.txt”的内容,而只是在结尾处读取。所以我想帮助将progressBarSim与main()结合起来。

* 编辑:* 我找到了一段代码:http://www.it-gecko.de/html5-file-upload-fortschrittanzeige-progressbar.html,现在正在使用它。

1 个答案:

答案 0 :(得分:0)

以下是适用于现代浏览器的ajax功能:

//url,callback,type,FormData,uploadFunc,downloadFunc
function ajax(a,b,e,d,f,g,c){
 c=new XMLHttpRequest;
 !f||(c.upload.onprogress=f);
 !g||(c.onprogress=g);
 c.onload=b;
 c.open(e||'get',a);
 c.send(d||null)
}

有关此功能的更多信息https://stackoverflow.com/a/18309057/2450730

这是html

<form><input type="file" name="file"><input type="submit" value="GO"></form>
<canvas width="64" height="64"></canvas>
<canvas width="64" height="64"></canvas>
<pre></pre>

您可以在表单中添加更多字段,而无需更改javascript函数中的任何内容。 它始终发送整个表单

这是使这个ajax功能起作用的代码

var canvas,pre;
window.onload=function(){
 canvas=document.getElementsByTagName('canvas');
 pre=document.getElementsByTagName('pre')[0];
 document.forms[0].onsubmit=function(e){
  e.preventDefault();
  ajax('upload.php',rdy,'post',new FormData(this),progressup,progressdown)
 }
}
function progressup(e){
 animate(e.loaded/e.total,canvas[0],'rgba(127,227,127,0.3)')
}
function progressdown(e){
 animate(e.loaded/e.total,canvas[1],'rgba(227,127,127,0.3)')
}
function rdy(e){
 pre.textContent=this.response;
}

这是移动圆形画布进度条的动画

function animate(p,C,K){
var c=C.getContext("2d"),
x=C.width/2,
r=x-(x/4),
s=(-90/180)*Math.PI,
p=p||0,
e=(((p*360|0)-90)/180)*Math.PI;
c.clearRect(0,0,C.width,C.height);
c.fillStyle=K;
c.textAlign='center'; 
c.font='bold '+(x/2)+'px Arial';
c.fillText(p*100|0,x,x+(x/5));
c.beginPath();
c.arc(x,x,r,s,e);
c.lineWidth=x/2;
c.strokeStyle=K;
c.stroke();
}

你可以扩展这个功能,在初始化或进行改变时有一些很好的反弹效果。

http://jsfiddle.net/vL7Mp/2/

测试我只是简单地使用像这样的upload.php文件

<?php
print_r(array('file'=>$_FILE,'post'=>$_POST));
?>

首先使用chrome测试它...然后应用必要的更改以便在旧浏览器中使用它...无论如何,此代码现在应该适用于所有最新的浏览器。

我明白这个功能并不容易理解......

如果您有任何疑问,请直接询问。

可能存在一些语法错误或缺少某些内容......因为我只是复制了整个函数并动态应用了一些更改。

其他一些有用的功能:

显示可读的文件大小:

https://stackoverflow.com/a/20463021/2450730

将MS转换为时间字符串或将时间字符串转换为MS

function ms2TimeString(a){
 var ms=a%1e3>>0,s=a/1e3%60>>0,m=a/6e4%60>>0,h=a/36e5%24>>0;
 return (h<10?'0'+h:h)+':'+(m<10?'0'+m:m)+':'+(s<10?'0'+s:s)+'.'+(ms<100?(ms<10?'00'+ms:'0'+ms):ms);
}
function timeString2ms(a){
 var ms=0,b;
 a=a.split('.');
 !a[1]||(ms+=a[1]*1);
 a=a[0].split(':'),b=a.length;
 ms+=(b==3?a[0]*3600+a[1]*60+a[2]*1:b==2?a[0]*60+a[1]*1:s=a[0]*1)*1e3;
 return ms
}

简单的PAD LEFT功能

function padL(a,b,c){//string,length=2,char=0
 return (new Array(b||2).join(c||0)+a).slice(-b);
}

ps.i'm还致力于转换进度条。如果你有兴趣,我可以告诉你我的进步。