2012-06-12 9 views
6

Ich versuche, eine Remote-Datei zu bekommen und erzwingen, es zum Benutzer zur gleichen Zeit herunterladen. Ich kann den Code nicht einfügen, der Code ist zu lang. aber die Curl-Funktion funktioniert, aber das Problem ist, dass es nichts ausgibt, bis es die Remote-Datei zuerst bekommt, dann erzwingt es Downloads für den Benutzer.locken Get Remote-Datei und erzwinge Download zur gleichen Zeit

Ich benutze diese curl anweisen, einen Rückruf ich diese

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

jetzt in meiner readCallback Funktion zurückzukehren:

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

aber es bis nur wartet nicht wieder etwas entfernten Abrufen Die Datei ist fertig.

+0

Warum Echo * und * zurück? – ThiefMaster

+0

Echo soll die heruntergeladenen Teile an den Benutzer ausgeben, und return ist für curl, weil es nach einem Rückgabewert von Callback fragt – Danny

+0

möglich Duplikat von [Exit aus einem cURL fetch] (http://stackoverflow.com/questions/9491621/ exit-out-a-curl-fetch) --- Sie suchen nach dem write callback, hier ein Beispiel (und wie Sie das debuggen können): [curl 'CURLOPT_WRITEFUNCTION' PHP-Beispiel] (http: //stackoverflow.com/a/9491855/367456) – hakre

Antwort

6

Versuchen Sie dies, wird es verwenden curl die Gesamtgröße der Datei erhalten dann Teilstücken der Datei, um es dem Benutzer Proxying herunterladen, um es keine für curl warten ist es zunächst herunterladen, Getestet habe ich diese mit avi, mp4, mp3 und eine exe, hoffe es hilft:

<?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

Für eine bessere Leistung in Betracht ziehen 'Readfile' und PHP-Stream-Kontexte in der Zukunft. Du wirst es lieben. – hakre

+0

Wir reden über Remote-Datei, ich liebe es, ein Beispiel zu sehen, was du meinst, als ich versucht habe, mich eine Stunde lang mit dieser Frage zu beschäftigen. :) –

+0

'readfile' arbeitet mit PHP-Streams, z.B. Sie können Remote-Dateien abrufen. Stream-Copy-Stream könnte auch etwas wert sein, wenn es möglich ist, direkt auf PHP-Ausgabe zu streamen (was ich auch für möglich halte). Ich denke jedoch, dass readfile noch etwas leichter ist. http://php.net/manual/en/book.stream.php; http://www.php.net/manual/en/stream.contexts.php und schließlich: http://ua2.php.net/manual/en/function.readfile.php – hakre

2

Try curl wie folgt aus:

$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(); 

Der Rückgabewert ist dann der Inhalt der angeforderten Datei, die Sie dann ausgegeben. Also keine Notwendigkeit für einen Rückruf. HTTPMessage docs.

+2

aber wartet das nicht, bis die Datei den Download beendet hat und dann ausgibt? – Danny

+0

Ja, aber ist das negativ? Die Übertragung sollte unglaublich schnell sein, da dies von einem Server zum anderen und wahrscheinlich viel schneller ist, als Ihre Client-Verbindung. Und Sie können diese Dateien lokal zwischenspeichern, damit der nächste Benutzer, der dieselbe Datei anfordert, eine schnellere Antwort erhält. Haben Sie den Unterschied der Downloadzeit der beiden Methoden gemessen? – Michael

+0

Nun möchte ich sie im Cache speichern, wie ich es dem Benutzer präsentiere, wie ich es auf den Server selbst herunterladen Ich lasse den Benutzer es auf der anderen Seite herunterladen und wie ich es herunterladen kann ich es selbst cachen, und die Benutzergeschwindigkeit kann nicht mehr sein als Server, selbst wenn es ist, kann ich es begrenzen. – Danny

Verwandte Themen