2012-06-12 12 views
6

Estoy tratando de obtener un archivo remoto y obligar a descargarlo al usuario al mismo tiempo. No puedo pegar el código, el código es demasiado largo. pero la función curl funciona, pero el problema es que no saca nada hasta que obtiene el archivo remoto primero y luego lo fuerza a descargarlo al usuario.curl obtener archivo remoto y descargar fuerza al mismo tiempo

Lo utilizo para decirle rizo para devolver una llamada de retorno

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

ahora en mi función readCallback hago esto:

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

pero no devuelve nada simplemente espera hasta que ir a buscar a distancia archivo está terminado.

+0

¿Por qué echo * y * return? – ThiefMaster

+0

echo es para enviar las partes descargadas al usuario, y el retorno es para curl porque solicita un valor de retorno de la devolución de llamada – Danny

+0

posible duplicado de [Salir de una búsqueda de CURL] (http://stackoverflow.com/questions/9491621/ exit-out-of-a-curl-fetch) --- Está buscando la devolución de llamada de escritura, vea aquí un ejemplo de trabajo (y cómo puede depurar eso): [curl 'CURLOPT_WRITEFUNCTION' Ejemplo de PHP] (http: //stackoverflow.com/a/9491855/367456) – hakre

Respuesta

6

Prueba esto, utilizará rizo para obtener el tamaño total del archivo se descarga trozos parciales del archivo de proxies al usuario de manera que no hay esperar de rizo para descargarlo primero, he probado esto con un avi, mp4, mp3 y un exe, espero que ayude:

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

Para un mejor rendimiento considere usar 'readfile' y contextos de flujo de PHP en el futuro. Lo amarás. – hakre

+0

Estamos hablando de archivos remotos, me encantaría ver un ejemplo de lo que quiere decir que he estado tratando de entender esta cuestión durante una hora. :) –

+0

'readfile' funciona con secuencias de PHP, p. puede hacer que busque archivos remotos. la secuencia de copia de secuencias también puede ser algo que valga la pena investigar si es posible transmitir directamente a la salida de PHP (lo cual también creo que es posible). Sin embargo, creo que readfile es un poco más ligero aún. http://php.net/manual/en/book.stream.php; http://www.php.net/manual/en/stream.contexts.php y finalmente: http://ua2.php.net/manual/en/function.readfile.php – hakre

2

Intente utilizar rizo de esta manera:

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

El valor de retorno es, pues, el contenido del archivo solicitado, que puede entonces enviar. Entonces no hay necesidad de una devolución de llamada. HTTPMessage docs.

+2

pero, ¿no espera esto hasta que el archivo termine la descarga por curl y luego lo muestre? – Danny

+0

Sí, pero ¿es negativo? La transferencia debe ser increíblemente rápida ya que es de un servidor a otro y probablemente mucho más rápido que la conexión de su cliente. Y puede almacenar en caché esos archivos localmente para que el siguiente usuario que solicite el mismo archivo obtenga una respuesta más rápida. ¿Has medido la diferencia de tiempo de descarga de los dos métodos? – Michael

+0

bueno, quiero guardarlos en caché como se lo presento al usuario, ya que lo descargo al servidor yo mismo dejo que el usuario lo descargue en otro lado y cuando lo descargo puedo guardarlo en caché, y la velocidad de los usuarios no puede ser mayor que los servidores, incluso si es que puedo limitarlo. – Danny

Cuestiones relacionadas