【问题标题】:Video File Upload Progress Bar with Javascript and PHP使用 Javascript 和 PHP 的视频文件上传进度条
【发布时间】:2014-02-18 14:11:12
【问题描述】:

我想使用 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是什么吗?看起来你没有,Ajax 用于调用 php 脚本并从中获取响应,而无需在浏览器中重新加载页面。所以你在这里使用的不是 Ajax,它不能工作,因为 php 将首先被完全执行。因此,当浏览器使用 main 函数时,文件说它已完成是合乎逻辑的。
  • 你也在使用 ffmpeg?
  • 我没有使用 ffmpeg,也没有太多的 javascript 和 ajax 经验,这就是我犯这个错误的原因。

标签: javascript php ajax


【解决方案1】:

这是现代浏览器的 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.我也在制作一个转换进度条。如果您有兴趣,我可以向您展示我的进度。

【讨论】:

  • 好的,这段代码似乎可以工作,但我很难理解 javascript 代码。我需要重写它,因为它似乎“打印_r”当前文件而没有在upload.php文件中指定它(我不知道为什么)。你不需要解决这个问题,我必须自己找出答案。问题是我不明白为什么它在没有'action =“”'标签的情况下工作,我不明白为什么它会变成“print_r”。我也不明白为什么我不能使用move_uploaded_file($_POST['file'], 'path/to/my/files');
  • 这是 html5 新的 FormData .. 不需要表单内的任何属性。print_r 只是在这里向您展示正在上传的内容。关于 php ...您可能对 max_upload_size .. max_execution_time max_post_size... 或某些权限有问题。
  • 好的,很好,我在 php.ini 中的这些值上对其进行了测试,但是在 upload.php 上执行它似乎有问题,无论我将脚本放在哪里或我如何设置路径,它不调用该文件,所以我不能使用 POST- 或 FILE 数据......我也在一个新项目中尝试过它,所有文件都在同一个文件夹中,它不加载“upload.php代码”用于小文件或大文件,也许你忘记了要复制的东西? (在此先感谢,这真的很棒!)
猜你喜欢
  • 2023-03-30
  • 2021-07-19
  • 1970-01-01
  • 2013-02-15
  • 2012-12-11
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
相关资源
最近更新 更多