2012-06-12 59 views
6

我试图获取远程文件并强制将其同时下载到用户。 我无法粘贴代码,代码太长。但curl函数的工作原理,但问题是它不会把任何东西,直到它首先获得远程文件,然后强制下载到用户。curl获取远程文件并强制同时下载

我使用它来卷曲告诉返回回调

curl_setopt($ch, CURLOPT_READFUNCTION, 'readCallback'); 

现在我readCallback功能我这样做:

function readCallback($curl, $stream, $maxRead){ 
    $read = fgets($stream, $maxRead); 
    echo $read; 
    return $read; 
} 

,但它不返回任何东西它只是等待,直到远程获取文件完成。

+0

为什么你回声*和*返回? – ThiefMaster

+0

回声是输出下载的部分给用户,并返回为卷曲,因为它要求从回调返回值 – Danny

+0

可能重复[退出cURL提取](http://stackoverflow.com/questions/9491621/退出卷曲获取)---你正在寻找写回调,在这里看到一个工作示例(以及如何调试它):[curl'CURLOPT_WRITEFUNCTION' PHP example](http: //stackoverflow.com/a/9491855/367456) – hakre

回答

6

试试这个,它将使用curl来获取文件的总大小,然后下载文件的部分块代理它给用户,因为没有等待 curl首先下载它,我测试了这个一个AVI,MP4,MP3和EXE,希望它有帮助:

<?php 
$file = 'http://example.com/somefile.mp3'; 
download($file,2000); 

/* 
Set Headers 
Get total size of file 
Then loop through the total size incrementing a chunck size 
*/ 
function download($file,$chunks){ 
    set_time_limit(0); 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-disposition: attachment; filename='.basename($file)); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Expires: 0'); 
    header('Pragma: public'); 
    $size = get_size($file); 
    header('Content-Length: '.$size); 

    $i = 0; 
    while($i<=$size){ 
     //Output the chunk 
     get_chunk($file,(($i==0)?$i:$i+1),((($i+$chunks)>$size)?$size:$i+$chunks)); 
     $i = ($i+$chunks); 
    } 

} 

//Callback function for CURLOPT_WRITEFUNCTION, This is what prints the chunk 
function chunk($ch, $str) { 
    print($str); 
    return strlen($str); 
} 

//Function to get a range of bytes from the remote file 
function get_chunk($file,$start,$end){ 
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $file); 
    curl_setopt($ch, CURLOPT_RANGE, $start.'-'.$end); 
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'chunk'); 
    $result = curl_exec($ch); 
    curl_close($ch); 
} 

//Get total size of file 
function get_size($url){ 
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_HEADER, true); 
    curl_setopt($ch, CURLOPT_NOBODY, true); 
    curl_exec($ch); 
    $size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); 
    return intval($size); 
} 
?> 
+0

为了获得更好的性能,考虑将来使用'readfile'和PHP流上下文。你会喜欢的。 – hakre

+0

如果你说的是远程文件,那么id很喜欢看到你的意思是一直试图让我的头在一个小时内解决这个问题。 :) –

+0

'readfile'适用于PHP流,例如您可以使其获取远程文件。如果可以直接流到PHP输出(我认为这也是可能的),那么流副本流可能是值得查看的东西。不过我认为readfile还是比较轻一点。 http://php.net/manual/en/book.stream.php; http://www.php.net/manual/en/stream.contexts.php最后:http://ua2.php.net/manual/en/function.readfile.php – hakre

2

尝试使用curl这样的:

$ch = curl_init($url); 
curl_setopt($ch, CURLOPT_HEADER, 1); 
curl_setopt($ch, CURLOPT_HTTPGET, 1); 
curl_setopt($ch, CURLOPT_TIMEOUT, 60); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 
$result = curl_exec($ch); 

$msg = new HttpMessage($result); 
return $msg->getBody(); 

返回值则是请求的文件的内容,你可以再输出。所以不需要回调。 HTTPMessage docs

+2

但是,这不等到文件通过curl完成下载然后输出它? – Danny

+0

是的,但是是否定的?传输速度应该非常快,因为这是从一台服务器到另一台服务器的速度,并且可能比您的客户端连接快得多。而且你可以在本地缓存这些文件,这样下一个请求同一文件的用户将得到更快的响应。你有没有测量两种方法下载时间的差异? – Michael

+0

以及我想缓存他们,因为我把它呈现给用户,因为我将它下载到服务器自己我让用户下载它在我下载它时我可以自己缓存它,并且用户速度不能更快即使是服务器,我也可以限制它。 – Danny