javascript - 使用 Javascript 和 PHP 实现视频文件上传进度条

标签 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);

进度条当前确实通过计时器工作,因为 main() 函数不会从开头读取“progress.txt”的内容,而只在末尾读取。所以我想得到一些帮助来将 ProgressBarSim 与 main() 结合起来。

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

最佳答案

这是现代浏览器的 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;
}

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

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.我还在研究转换进度条。如果您有兴趣,我可以向您展示我的进步。

关于javascript - 使用 Javascript 和 PHP 实现视频文件上传进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21856343/

相关文章:

php - mpdf addPage 创建空白页

php - 在类包装器中缓存 PDO 准备语句

javascript - RoutingError(没有路由匹配[选项]

javascript - 无法使用ajax序列化功能将图像插入数据库

javascript - Jqgrid树形网格按行ID滚动到行并展开节点(如果折叠)

javascript - 循环加载多个图像并向每个图像添加监听器

java - 如何制作Web App在线编译运行Java/C/PHP代码?

jquery - 使用 jQuery ajax get 将 params 中的数据发送到 Rails 后端

javascript - Chrome 忽略 jquery 点击功能

javascript - 为什么 redux thunk 返回 Promise?