我有一个输入字段,可以在其中粘贴下载网址。
之后,我使用 AJAX 请求来获取文件信息,例如 headerinfo、内容长度、mime 类型,如果我使用curl 接受范围。
然后,我开始连续循环 xhr2 请求,其中包含我的 php 文件的范围。
http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=0-1024
http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=1024-2048
....
我也可以将其更改为
http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=0-1024
http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=1025-2049
....
取决于我的脚本开始读取文件的位置。
我的第一个方法是使用 cUrl 并设置范围
<?php
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_RANGE,$_GET['range']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$result=curl_exec($ch);
curl_close($ch);
echo $result;
?>
效果很好,但如果范围块大于 1mb,客户端就没有动画onprogress
使用ajax的事件。
我可能会使用自定义的CURLOPT_READFUNCTION
...但我不知道这是如何工作的...所以我改变了方法并使用了简单的fopen
<?php
$r=explode('-',$_GET['range']);//get (from to) ranges
$cc=($r[1]-$r[0]); //Calculate Client Chunk length
$sc=128; //Set the Server chunk length
$b=""; //Buffer
$bytes=0; //bytes read
$h=fopen($_GET['url'],"rb"); // open the url
fseek($h,$r[0]); // jump to the from pointer retrieved from links
while($bytes<$cc){ //while bytes read is smaller than my client chunk
$sc=(($bytes+$sc)>$cc?($cc-$bytes):$sc); //prolley an error here
//if the server chunk + bytes read is bigger than the client chunk
//then the server chunk is clinet chunk - bytes read
$b=fread($h,$sc); // read the buffer
$bytes+=strlen($b); //add the buffer length to bytes read
echo $b;// echo the buffer
ob_flush(); // flush
flush(); // flush
}
fclose($h); //close
?>
现在这有效了...我在客户端上获得了正确的动画,并且最终大小也是正确的,当我使用 fseek && fread 时,指针应该没问题(0-1024,1024-2048)。
但文件已损坏。
现在经过一些测试......这非常慢。
更好的方法是cUrl
with CURLOPT_READFUNCTION
or fsoket
打开...
所以我猜:
<?php
function $READ(){
//here i need small chuncks of the response flushed.
}
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_RANGE,$_GET['range']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_READFUNCTION,$READ);
$result=curl_exec($ch);
curl_close($ch);
echo $result;
?>
如果您有更好的解决方案,我愿意接受使用 javascript 和 php 的所有内容。
这样做的目的是创建一个带有简历的下载管理器,将文件存储到window.webkitRequestFileSystem
而不填充浏览器的内存。
假设客户端有 8mb 的块,服务器块有 256kb ..
然后该块的每 8mb 都会附加到之前使用以下命令创建的文件中window.webkitRequestFileSystem
每 256kb 我都会更新一次平均下载速度,这样我就可以创建一个漂亮的动画。
服务器上的 php 仅使用 256kb ram,客户端浏览器可以每 8mb 清空一次垃圾收集(理论上)。
EDIT2
对于这段代码我找到了一个解决方案:
该代码允许您获取范围,例如:0-100
并得到这 100 字节分块的输出!
这允许您拥有一个具有连续完美进度条的 AJAX 脚本
<?php
function w($ch,$chunk){
echo $chunk;
ob_flush();
flush();
return strlen($chunk);
};
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_RANGE,$_GET['range']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_WRITEFUNCTION,w);
curl_exec($ch);
curl_close($ch);
?>
但我希望你们有更好的解决方案!谢谢