2012-06-12 7 views
6

Próbuję uzyskać zdalny plik i wymuszam pobieranie go do użytkownika w tym samym czasie. Nie mogę wkleić kodu, kod jest za długi. ale funkcja curl działa, ale problem polega na tym, że nie umieszcza niczego, dopóki nie pobierze najpierw pliku zdalnego, a potem zmusi go do pobrania.curl get zdalny plik i wymuszenie pobrania w tym samym czasie

Używam tego powiedzieć curl wrócić wywołania zwrotnego

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

Teraz w mojej funkcji readCallback Mam to:

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

ale to nie ma nic po prostu czeka, aż powróci zdalnego pobierania plik został zakończony.

+0

Dlaczego echo * i * powrót? – ThiefMaster

+0

echo służy do wyprowadzania pobranych części do użytkownika, a powrót jest zwinięty, ponieważ prosi o zwrócenie wartości z oddzwonienia – Danny

+0

możliwy duplikat [Wyjście z pobierania cURL] (http://stackoverflow.com/questions/9491621/ exit-out-of-a-curl-fetch) --- Szukasz zapisu zwrotnego, zobacz tutaj dla przykładu (i jak możesz to debugować): [curl 'CURLOPT_WRITEFUNCTION' przykład PHP] (http: //stackoverflow.com/a/9491855/367456) – hakre

Odpowiedz

6

Spróbuj tego użyć curl, aby uzyskać całkowity rozmiar pliku, a następnie pobrać częściowe fragmenty pliku proxy dla użytkownika, tak, aby nie było czekać na ściągnięcie go, przetestowałem to z avi, mp4, mp3 i exe, mam nadzieję, że pomoże:

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

Dla lepszej wydajności rozważ użycie kontekstów 'readfile' i PHP stream w przyszłości. Będzie Ci się podobało. – hakre

+0

Rozmawialiśmy o zdalnym pliku, id kochanie, aby zobaczyć przykład, co masz na myśli, gdy próbowałem zrozumieć moją kwestię przez godzinę. :) –

+0

'readfile' działa ze strumieniami PHP, np. możesz zmusić go do pobierania zdalnych plików. strumień strumienia strumieniowego może być również wart uwagi, jeśli możliwe jest bezpośrednie przesyłanie strumieniowe do wyjścia PHP (co moim zdaniem jest również możliwe). Jednak myślę, że readfile jest jeszcze trochę lżejszy. http://php.net/manual/en/book.stream.php; http://www.php.net/manual/en/stream.contexts.php i wreszcie: http://ua2.php.net/manual/en/function.readfile.php – hakre

2

Spróbuj użyć pozwijane tak:

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

Wartością zwracaną następnie jest treść żądanego pliku, który można następnie wyjście. Więc nie ma potrzeby połączenia zwrotnego. HTTPMessage docs.

+2

ale czy to nie czeka, aż plik zakończy pobieranie przez curl, a następnie wypisze? – Danny

+0

Tak, ale czy to jest negatywne? Transfer powinien być niesamowicie szybki, ponieważ jest on z jednego serwera na drugi i prawdopodobnie o wiele szybszy niż połączenie z klientem. Można również buforować te pliki lokalnie, aby następny użytkownik żądający tego samego pliku uzyskał szybszą odpowiedź. Czy zmierzyłeś różnicę czasu pobierania dwóch metod? – Michael

+0

cóż, chcę je przechowywać w pamięci podręcznej, ponieważ przedstawiam je użytkownikowi, ponieważ sam ściągam go na serwer, pozwalam użytkownikowi pobierać go na drugą stronę, a kiedy go pobierze, mogę go samodzielnie buforować, a prędkość użytkowników nie może być większa niż serwery, nawet jeśli mogę to ograniczyć. – Danny

Powiązane problemy