Foros del Web » Programando para Internet » PHP »

Problemas para forzar descarga

Estas en el tema de Problemas para forzar descarga en el foro de PHP en Foros del Web. Qué tal: Tengo problemas con un script para forzar la descarga de archivos. Al descargarlos, si son pesados, los archivos se descargan de manera parcial. ...
  #1 (permalink)  
Antiguo 01/04/2008, 12:28
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Pregunta Problemas para forzar descarga

Qué tal:

Tengo problemas con un script para forzar la descarga de archivos. Al descargarlos, si son pesados, los archivos se descargan de manera parcial.

Creí que era el servidor, pero intenté descargarlos sin usar el script y se descargan completitos y sin problemas.

¿Qué ocurre?

Se supone que estoy especificando en las cabeceras el peso del archivo. El tipo de archivo que deseo descargar es MP3, solamente, y pesa más de 10 MB, se descargan sólo 4 o 5 o 6 MB.

Este es mi código:

Código PHP:
    $extensiones = array("mp3""doc""pdf""flv");
    
$f $_GET["file"];
    if(
strpos($f,"/")!==false){
        die(
"No es posible navegar por otros directorios");
    }
    
$ftmp explode(".",$f);
    
$fExt strtolower($ftmp[count($ftmp)-1]);
    
    if(
$f == ""){
        die(
"No se ha especificado ningún archivo para descargar");
    } elseif (!
in_array($fExt,$extensiones)){
        die(
"<strong>ERROR!</strong> no es posible descargar archivos con la extensión <strong>$fExt</strong>");
    } elseif (! 
file_exists($f)){
        die(
"<strong>ERROR!</strong> no se ha encontrado ningún archivo titulado <strong>$f</strong>");
    };

    switch( 
$fExt )
    {
      case 
"pdf"$ctype="application/pdf"; break;
      case 
"mp3"$ctype="audio/mpeg3"; break;
      case 
"zip"$ctype="application/zip"; break;
      case 
"doc"$ctype="application/msword"; break;
      case 
"xls"$ctype="application/vnd.ms-excel"; break;
      case 
"ppt"$ctype="application/vnd.ms-powerpoint"; break;
      case 
"gif"$ctype="image/gif"; break;
      case 
"png"$ctype="image/png"; break;
      case 
"jpg"$ctype="image/jpg"; break;
      default: 
$ctype="application/force-download";
    }

    
header("Pragma: public"); // required
    
header("Expires: 0");
    
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    
header("Cache-Control: private",false); // required for certain browsers 
    
header("Content-Type: $ctype");
    
// change, added quotes to allow spaces in filenames, by Rajkumar Singh
    
header("Content-Disposition: attachment; filename=\"$f\"\n");
    
header("Content-Transfer-Encoding: binary");
    
header("Content-Length: ".filesize($f));
    
readfile("$f");
    exit(); 
Gracias de antemano.
  #2 (permalink)  
Antiguo 01/04/2008, 13:12
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Re: Problemas para forzar descarga

Hola yconoclasta,

El problema es el tiempo limite de ejecución de tu script, prueba poner set_time_limit(0) al inicio de tu script.

Saludos.
  #3 (permalink)  
Antiguo 01/04/2008, 15:56
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Pregunta Re: Problemas para forzar descarga

Ya agregué esa linea y no solucionó nada.

¿Alguna otra idea?

Gracias.
  #4 (permalink)  
Antiguo 01/04/2008, 16:03
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Re: Problemas para forzar descarga

Incrementa el memory_limit, ya que readfile tiende a cargar todo el archivo en memoria. El memory_limit lo cambias en el php.ini.

Saludos.
  #5 (permalink)  
Antiguo 01/04/2008, 16:34
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Pregunta Re: Problemas para forzar descarga

Imposible. El servidor no es mío, es de pago. Yo sólo tengo acceso FTP.

No entiendo, el script lo único que se supone hace es decirle al navegador "no abras este archivo aunque tengas un plugin adecuado, descargalo" Entonces, comienza a funcionar el motor de descarga del navegador y el script ha dejado de utilizarse.

Entonces el archivo se comienza a descargar sin la ayuda del script.

En lo que hacía pruebas, en una de ellas descubrí que utilizando un gestor de descargas el archivo ni siquiera se descargaba, ya que el gestor indicaba que no correspondía el tamaño del archivo en el servidor con el tamaño del archivo que se pretendía descargar.

Ahora, sí comienza la descarga con el gestor, pero llegado a un cierto punto, variable, el gestor se detiene e indica el mismo problema de tamaños de archivo no coincidentes.

¿El problema no será en cómo estoy llamando el tamaño del archivo?

Saludos.
  #6 (permalink)  
Antiguo 01/04/2008, 17:13
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Re: Problemas para forzar descarga

Si no puedes cambiar las directivas entonces cambia la directiva read_file por fopen/fread/fclose, para entonces leer el archivo secuencialmente e ir liberando memoria.

Saludos.
  #7 (permalink)  
Antiguo 03/04/2008, 17:49
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Pregunta Re: Problemas para forzar descarga

También intenté cambiar por fopen, pero sigue sin funcionar. ¿Alguien sábe cuál puede ser la razón de esto? Sabiendo el porque creo que es más sencillo encontrar la solución.

Por lo que he buscado veo que el código es muy similar o identico al publicado en varios lugares referente a forzar descarga. No entiendo qué pasa.

aquí el código con las modificaciones:

Código PHP:
set_time_limit(0);
$extensiones = array("mp3""doc""pdf""flv");
$f $_GET["file"];
if(
strpos($f,"/")!==false){
    die(
"No es posible navegar por otros directorios");
}
$ftmp explode(".",$f);
$fExt strtolower($ftmp[count($ftmp)-1]);

if(
$f == ""){
    die(
"No se ha especificado ningún archivo para descargar");
} elseif (!
in_array($fExt,$extensiones)){
    die(
"<strong>ERROR!</strong> no es posible descargar archivos con la extensión <strong>$fExt</strong>");
} elseif (! 
file_exists($f)){
    die(
"<strong>ERROR!</strong> no se ha encontrado ningún archivo titulado <strong>$f</strong>");
};

switch( 
$fExt )
{
    case 
"pdf"$ctype="application/pdf"; break;
    case 
"exe"$ctype="application/octet-stream"; break;
    case 
"zip"$ctype="application/zip"; break;
    case 
"doc"$ctype="application/msword"; break;
    case 
"xls"$ctype="application/vnd.ms-excel"; break;
    case 
"ppt"$ctype="application/vnd.ms-powerpoint"; break;
    case 
"gif"$ctype="image/gif"; break;
    case 
"png"$ctype="image/png"; break;
    case 
"jpeg":
    case 
"jpg"$ctype="image/jpg"; break;
    case 
"wmv"$ctype="video/wmv"; break;
    case 
"mpg":
    case 
"mpeg"$ctype="video/mpg"; break;
    case 
"avi"$ctype="video/x-msvideo"; break;
    case 
"mov"$ctype="video/quicktime"; break;
    case 
"mp3"$ctype="audio/mp3"; break;
    case 
"wav"$ctype="audio/x-wav"; break;
    default: 
$ctype="application/octet-stream"; break;
}

header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers 
header("Content-Type:" .$ctype);
// change, added quotes to allow spaces in filenames, by Rajkumar Singh
header("Content-Disposition: attachment; filename=\"$f\"\n");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($f));
ob_clean();
flush();
ob_flush();
$fp=fopen("$f""r");
fpassthru($fp);
//$contenido = fread($fp, filesize($f));
//fclose($fp);
//fpassthru($fp);
//readfile("$f");
exit(); 
  #8 (permalink)  
Antiguo 03/04/2008, 21:39
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Re: Problemas para forzar descarga

El problema es que usando fpassthru pasa lo mismo que readfile. Prueba este código:
Código PHP:
ob_clean();
flush();
ob_flush();
$fp=fopen("$f""r");
while(!
feof($fp)) {
       echo 
fread$fp1024 );
}
fclose$fp );
//$contenido = fread($fp, filesize($f));
//fclose($fp);
//fpassthru($fp);
//readfile("$f");
exit(); 
Saludos.
  #9 (permalink)  
Antiguo 04/04/2008, 11:25
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Pregunta Re: Problemas para forzar descarga

Muchas gracias por tus respuestas GatorV, sin embargo, sigue sin funcionar

Estoy pensando en poner un enlace directo y pedir que descarguen los audios dando clic derecho y luego "guardar destino como".
  #10 (permalink)  
Antiguo 04/04/2008, 11:35
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Re: Problemas para forzar descarga

Mmm muy raro, cual es el limite que tienes definido en el memory_limit del php.ini?

Saludos.
  #11 (permalink)  
Antiguo 04/04/2008, 13:38
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Pregunta Re: Problemas para forzar descarga

Segun el phpinfo() es:
memory_limit 120M 120M

Saludos.
  #12 (permalink)  
Antiguo 04/04/2008, 15:15
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Re: Problemas para forzar descarga

Muy raro, entonces no veo porque no debería de funcionar correctamente, si ya estas usando set_time_limit(0).

Saludos.
  #13 (permalink)  
Antiguo 04/04/2008, 16:47
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Re: Problemas para forzar descarga

Alguna otra idea?
  #14 (permalink)  
Antiguo 04/04/2008, 17:08
Avatar de oso96_2000  
Fecha de Ingreso: junio-2002
Ubicación: Distrito Federal
Mensajes: 558
Antigüedad: 21 años, 10 meses
Puntos: 35
Re: Problemas para forzar descarga

Yo tengo esto por ahi y hasta ahora me ha servido para forzar la descarga de archivos, incluso aunque estos sean pesados:

$fullpath = '/ruta/a/tu/archivo.mp3';

Código PHP:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private"false);
header("Content-Transfer-Encoding: binary");
header("Content-Type: application/octet-stream");
header("Content-Length: " filesize($fullpath));
header("Content-Disposition: attachment; filename=" basename($fullpath));
readfile($fullpath);
exit(); 
Lo que yo creo que pasa contigo, es el Content-Type que mandas. Dejale para todo tipo de archivo el application/octet-stream como Content-Type y a ver que pasa. Tambien si asi lo deseas (y parece que sería recomendable), puedes cambiar el readfile() por lo que dijo GatorV de usar fopen/fread

Saludos
__________________
Sin Ideas
  #15 (permalink)  
Antiguo 04/04/2008, 17:10
 
Fecha de Ingreso: abril-2008
Ubicación: Querétaro, Mexico
Mensajes: 44
Antigüedad: 16 años
Puntos: 2
Re: Problemas para forzar descarga

si tu servidor es linux, podrias ver los permisos que tengas tus archivos

deben de tener permisos de ejecucion, a mi me pasaba eso. chmod 755

y es imposible ver el error porque como mandas el header no ves los errores en el navegador.



esto se puede hacer con tu cliente de ftp


espero que te ayude esto,


saludos,
Carlos Alejandro
  #16 (permalink)  
Antiguo 05/04/2008, 10:16
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Re: Problemas para forzar descarga

Gracias por sus respuestas e interes. Verifiqué los permisos y todos están en 755.

El Content-Type: application/octet-stream ya también lo especifiqué de esa manera. Nada.

Le escribí al soporte del hosting a ver si me dan una respuesta.

Seguiré buscando.

Gracias.
  #17 (permalink)  
Antiguo 05/04/2008, 10:34
Avatar de Carlojas  
Fecha de Ingreso: junio-2007
Ubicación: Shikasta
Mensajes: 1.272
Antigüedad: 16 años, 10 meses
Puntos: 49
Re: Problemas para forzar descarga

Mira estos dos post creo que te pueden servir:

1. Forzar descarga de un archivo
2. http://www.forosdelweb.com/f18/aport...te-1-a-561439/


Saludos.
  #18 (permalink)  
Antiguo 12/04/2008, 20:50
 
Fecha de Ingreso: febrero-2005
Mensajes: 135
Antigüedad: 19 años, 2 meses
Puntos: 0
Re: Problemas para forzar descarga

Muchas gracias por la ayuda a todos.

Leí los artículos que enviaron, realmente no aportan mucho de nuevo al còdigo que ya tengo.

El soporte técnico de mi hosting me respondió que los scripts PHP tienen un timeout de 60 segundos, por ello que las descargas no se acompleten. No es posible que ellos aumenten ese timeout.

Tomé el tiempo en el que tarda en romperse la descarga, y efectivamente son 60 seg.

Mi pregunta ahora es, ¿hay alguna manera de brincarse esa limitante?

Ya probé con set_time_limit(0); pero no lo respeta el servidor.

Saludos.
  #19 (permalink)  
Antiguo 13/04/2008, 00:32
 
Fecha de Ingreso: abril-2008
Ubicación: Querétaro, Mexico
Mensajes: 44
Antigüedad: 16 años
Puntos: 2
Re: Problemas para forzar descarga

hola, oye viendo que es imposible aumentar el tiempo de ejecucion de tu servidor, estoy pensando..

porque no despues de que checas todo q sea el tipo de archivo y el directorio y todo lo q haga tu script, en vez de enviar el archivo a traves de php, redireccionas al usuario al archivo fisico. asi tu php termina, y ya el usuario descarga desde la ubicacion "fisica" o actual del archivo.

esto lo puedes hacer con:

Código PHP:
header("Location: ruta/a/tu/archivo.pdf"); //esta ruta, es la que el cliente va a ir automaticamente. 
acuerdate que cuando mandas un header, no mandes nada mas antes ej un echo o print ya que esto genera error.


saludos,
Carlos Alejandro
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:12.