我想使用 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;
}
这是移动圆形画布进度条的动画
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();
}
您可以在初始化或进度更改时使用一些不错的反弹效果来扩展此功能。
为了测试我只需使用这样的 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.我还在研究转换进度条。如果您有兴趣,我可以向您展示我的进步。