Foros del Web » Programando para Internet » PHP »

Descargar archivos con PHP

Estas en el tema de Descargar archivos con PHP en el foro de PHP en Foros del Web. Hola gente les comento lo que necesito hacer: Tengo una tabla MySQL de productos donde el campo codigo más la extensión .jpg indica el nombre ...
  #1 (permalink)  
Antiguo 22/11/2013, 13:21
 
Fecha de Ingreso: mayo-2003
Mensajes: 523
Antigüedad: 20 años, 11 meses
Puntos: 6
Descargar archivos con PHP

Hola gente les comento lo que necesito hacer:

Tengo una tabla MySQL de productos donde el campo codigo más la extensión .jpg indica el nombre de su fotografía, la cual se encuentra una subcarpeta fotos. Hay también un campo que divide los productos por rubro (relojes, mochiles, deportivos, etc.)
Lo que mi cliente me pide es que el pueda seleccionar un rubro y un programa le descargue a su PC todas las fotos del mismo.
Entonces mi plan es una consulta SQL que me traiga todos los productos del rubro seleccionado y recorrerlos con un ciclo While. Hasta ahí todo bien, lo que no logro es descargar las fotos. He probado el código que les pego más abajo pero sólo me descarga la primera foto y se detiene (a pesar de que estoy seguro que el ciclo while recorre toda la lista de productos). Agradeceré cualquier pista:

<?
$codigo=$_GET['rubro'];
$productos=mysql_query("SELECT * FROM productos WHERE empresa='$codigo' ORDER BY codigo",$link);
while($producto=mysql_fetch_array($productos))
{

$archivo_remoto='fotos/'.$producto['codigo'].'.jpg';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
}
}

?>
  #2 (permalink)  
Antiguo 22/11/2013, 14:49
Avatar de quinqui  
Fecha de Ingreso: agosto-2004
Ubicación: Chile!
Mensajes: 776
Antigüedad: 19 años, 8 meses
Puntos: 56
Respuesta: Descargar archivos con PHP

Holas, Integer78.

Lo que te piden igual es algo rebuscado. Es casi un gestor de descargas... Lo que creo que pasa con tu código es que, si mal no recuerdo, cuando abres un archivo con PHP (usando el header() y todo eso), finalizas la ejecución del script. O sea, se supone que al ejecutar header() estás haciendo que el script PHP genere un archivo de X tipo, y hasta ahí llega, ya que el script deja de ser script y se ha transformado en el archivo invocado.

Para tu caso, pienso en dos soluciones:

a) Ya que tienes la lista de fotos, mostrarlas al cliente como una lista de archivos para descargar, como el clásico navegador de archivos, donde el cliente tendrá que descargarlas una a una.

b) Mediante alguna función interna de comunicación entre PHP y el server, ejecutar un programa de compresión de archivos, que precisamente comprima todos los que ya tienes identificados, y ejecutes header() para el archivo comprimido.

Son ideas :)

Saludos!
__________________
pipus.... vieeeeeji plomius!!!
*quinqui site*
  #3 (permalink)  
Antiguo 22/11/2013, 14:56
Avatar de Dalam  
Fecha de Ingreso: septiembre-2010
Mensajes: 409
Antigüedad: 13 años, 7 meses
Puntos: 56
Respuesta: Descargar archivos con PHP

a donde quieres descargar las imagenes, al servidor o que mas descargue un navegador o algo parecido.

Si es al servidor con un simple file_get_contents te sobra.
Si por el contrario lo que quieres es que se las descargue desde el navegador, podrias hacerlo mediante AJAX y forzando la descarga del archivo
  #4 (permalink)  
Antiguo 22/11/2013, 14:59
Avatar de Nemutagk
Colaborador
 
Fecha de Ingreso: marzo-2004
Ubicación: México
Mensajes: 2.633
Antigüedad: 20 años
Puntos: 406
Respuesta: Descargar archivos con PHP

Te das cuentas que estas "imprimiendo" el código binario de TODAS las imágenes que encuentras? eso es totalmente ilógico, lo que tendrías que hacer es separar la tarea de obtener la lista de imágenes en un archivo y genere una estructura html, al enviar el código generado (HTML) al navegador este llame a otro archivo usando por ejemplo un tag img y que el archivo PHP que envíe las cabeceras y el código binario de cada imagen...
__________________
Listo?, tendría que tener 60 puntos menos de IQ para considerarme listo!!!
-- Sheldon Cooper
http://twitter.com/nemutagk
PD: No contestaré temas vía mensaje personal =)
  #5 (permalink)  
Antiguo 22/11/2013, 15:01
Avatar de Dalam  
Fecha de Ingreso: septiembre-2010
Mensajes: 409
Antigüedad: 13 años, 7 meses
Puntos: 56
Respuesta: Descargar archivos con PHP

Otra opcion es que comprimas todas las imagenes en un archivo y le sirvas al cliente todas las imagenes juntas.
Si vas a usar esta ultima opcion, recuerda que las imagenes ganan muy poco con la compresion, asique no le des compresion, para asi ganar tiempo en la creacion del archivo.

Tambien en todas las opciones que tienes, tienes que tener en cuenta el time_limit, para que no te diga el navegador que se a agotado el tiempo
  #6 (permalink)  
Antiguo 26/11/2013, 09:51
Avatar de Dalam  
Fecha de Ingreso: septiembre-2010
Mensajes: 409
Antigüedad: 13 años, 7 meses
Puntos: 56
Respuesta: Descargar archivos con PHP

Para comprimirlo en archivo zip y por si acaso tu configuracion de php no tiene la opcion de usar archivos zip, vamos a usar una clase creada por Eric Mueller

Código PHP:
<?php  
/* 
Zip file creation class 
makes zip files on the fly... 

use the functions add_dir() and add_file() to build the zip file; 
see example code below 

by Eric Mueller 
http://www.themepark.com 

v1.1 9-20-01 
  - added comments to example 

v1.0 2-5-01 

initial version with: 
  - class appearance 
  - add_file() and file() methods 
  - gzcompress() output hacking 
by Denis O.Philippov, [email protected], http://www.atlant.ru 

*/  

// official ZIP file format: http://www.pkware.com/appnote.txt 

class zipfile   
{   

    var 
$datasec = array(); // array to store compressed data 
    
var $ctrl_dir = array(); // central directory    
    
var $eof_ctrl_dir "\x50\x4b\x05\x06\x00\x00\x00\x00"//end of Central directory record 
    
var $old_offset 0;  

    function 
add_dir($name)    

    
// adds "directory" to archive - do this before putting any files in directory! 
    // $name - name of directory... like this: "path/" 
    // ...then you can add files using add_file with names like "path/file.txt" 
    
{   
        
$name str_replace("\\""/"$name);   

        
$fr "\x50\x4b\x03\x04";  
        
$fr .= "\x0a\x00";    // ver needed to extract 
        
$fr .= "\x00\x00";    // gen purpose bit flag 
        
$fr .= "\x00\x00";    // compression method 
        
$fr .= "\x00\x00\x00\x00"// last mod time and date 

        
$fr .= pack("V",0); // crc32 
        
$fr .= pack("V",0); //compressed filesize 
        
$fr .= pack("V",0); //uncompressed filesize 
        
$fr .= pack("v"strlen($name) ); //length of pathname 
        
$fr .= pack("v"); //extra field length 
        
$fr .= $name;   
        
// end of "local file header" segment 

        // no "file data" segment for path 

        // "data descriptor" segment (optional but necessary if archive is not served as file) 
        
$fr .= pack("V",$crc); //crc32 
        
$fr .= pack("V",$c_len); //compressed filesize 
        
$fr .= pack("V",$unc_len); //uncompressed filesize 

        // add this entry to array 
        
$this -> datasec[] = $fr;  

        
$new_offset strlen(implode(""$this->datasec));  

        
// ext. file attributes mirrors MS-DOS directory attr byte, detailed 
        // at http://support.microsoft.com/support/kb/articles/Q125/0/19.asp 

        // now add to central record 
        
$cdrec "\x50\x4b\x01\x02";  
        
$cdrec .="\x00\x00";    // version made by 
        
$cdrec .="\x0a\x00";    // version needed to extract 
        
$cdrec .="\x00\x00";    // gen purpose bit flag 
        
$cdrec .="\x00\x00";    // compression method 
        
$cdrec .="\x00\x00\x00\x00"// last mod time & date 
        
$cdrec .= pack("V",0); // crc32 
        
$cdrec .= pack("V",0); //compressed filesize 
        
$cdrec .= pack("V",0); //uncompressed filesize 
        
$cdrec .= pack("v"strlen($name) ); //length of filename 
        
$cdrec .= pack("v"); //extra field length    
        
$cdrec .= pack("v"); //file comment length 
        
$cdrec .= pack("v"); //disk number start 
        
$cdrec .= pack("v"); //internal file attributes 
        
$ext "\x00\x00\x10\x00";  
        
$ext "\xff\xff\xff\xff";   
        
$cdrec .= pack("V"16 ); //external file attributes  - 'directory' bit set 

        
$cdrec .= pack("V"$this -> old_offset ); //relative offset of local header 
        
$this -> old_offset $new_offset;  

        
$cdrec .= $name;   
        
// optional extra field, file comment goes here 
        // save to array 
        
$this -> ctrl_dir[] = $cdrec;   

          
    }  


    function 
add_file($data$name)    

    
// adds "file" to archive    
    // $data - file contents 
    // $name - name of file in archive. Add path if your want 

    
{   
        
$name str_replace("\\""/"$name);   
        
//$name = str_replace("\\", "\\\\", $name); 

        
$fr "\x50\x4b\x03\x04";  
        
$fr .= "\x14\x00";    // ver needed to extract 
        
$fr .= "\x00\x00";    // gen purpose bit flag 
        
$fr .= "\x08\x00";    // compression method 
        
$fr .= "\x00\x00\x00\x00"// last mod time and date 

        
$unc_len strlen($data);   
        
$crc crc32($data);   
        
$zdata gzcompress($data);   
        
$zdata substrsubstr($zdata0strlen($zdata) - 4), 2); // fix crc bug 
        
$c_len strlen($zdata);   
        
$fr .= pack("V",$crc); // crc32 
        
$fr .= pack("V",$c_len); //compressed filesize 
        
$fr .= pack("V",$unc_len); //uncompressed filesize 
        
$fr .= pack("v"strlen($name) ); //length of filename 
        
$fr .= pack("v"); //extra field length 
        
$fr .= $name;   
        
// end of "local file header" segment 
          
        // "file data" segment 
        
$fr .= $zdata;   

        
// "data descriptor" segment (optional but necessary if archive is not served as file) 
        
$fr .= pack("V",$crc); //crc32 
        
$fr .= pack("V",$c_len); //compressed filesize 
        
$fr .= pack("V",$unc_len); //uncompressed filesize 

        // add this entry to array 
        
$this -> datasec[] = $fr;  

        
$new_offset strlen(implode(""$this->datasec));  

        
// now add to central directory record 
        
$cdrec "\x50\x4b\x01\x02";  
        
$cdrec .="\x00\x00";    // version made by 
        
$cdrec .="\x14\x00";    // version needed to extract 
        
$cdrec .="\x00\x00";    // gen purpose bit flag 
        
$cdrec .="\x08\x00";    // compression method 
        
$cdrec .="\x00\x00\x00\x00"// last mod time & date 
        
$cdrec .= pack("V",$crc); // crc32 
        
$cdrec .= pack("V",$c_len); //compressed filesize 
        
$cdrec .= pack("V",$unc_len); //uncompressed filesize 
        
$cdrec .= pack("v"strlen($name) ); //length of filename 
        
$cdrec .= pack("v"); //extra field length    
        
$cdrec .= pack("v"); //file comment length 
        
$cdrec .= pack("v"); //disk number start 
        
$cdrec .= pack("v"); //internal file attributes 
        
$cdrec .= pack("V"32 ); //external file attributes - 'archive' bit set 

        
$cdrec .= pack("V"$this -> old_offset ); //relative offset of local header 
//        echo "old offset is ".$this->old_offset.", new offset is $new_offset<br>"; 
        
$this -> old_offset $new_offset;  

        
$cdrec .= $name;   
        
// optional extra field, file comment goes here 
        // save to central directory 
        
$this -> ctrl_dir[] = $cdrec;   
    }  

    function 
file() { // dump out file    
        
$data implode(""$this -> datasec);   
        
$ctrldir implode(""$this -> ctrl_dir);   

        return    
            
$data.   
            
$ctrldir.   
            
$this -> eof_ctrl_dir.   
            
pack("v"sizeof($this -> ctrl_dir)).     // total # of entries "on this disk" 
            
pack("v"sizeof($this -> ctrl_dir)).     // total # of entries overall 
            
pack("V"strlen($ctrldir)).             // size of central dir 
            
pack("V"strlen($data)).                 // offset to start of central dir 
            
"\x00\x00";                             // .zip file comment length 
    
}  
}   

?>
Despues de crear el script de la clase, comenzamos a usar la clase para enviarle al usuario el archivo comprimido con todas las imagenes dentro


El script que usas, deberia quedar asi

Código PHP:
<?php
    
require ("zipfile.php");// ruta a el archivo de la clase anteriormente mencionada
    
$zipfile = new zipfile(); // creamos el objeto zip
    
$codigo=$_GET['rubro']; 
    
$productos=mysql_query("SELECT * FROM productos WHERE empresa='$codigo' ORDER BY codigo",$link);
    
//Creamos el objeto zipfile
    
    
while($producto=mysql_fetch_array($productos)){
        
$archivo_remoto='fotos/'.$producto['codigo'].'.jpg'
        if (
file_exists($archivo_remoto)){
            
$zipfile->add_file(implode("",file($archivo_remoto)), $producto['codigo'].'.jpg');
        }
    }
    
// Una vez agregados todos los archivos , enviamos las cabeceras y el archivo
    
header("Content-type: application/octet-stream");
    
header("Content-disposition: attachment; filename=zipfile.zip");
    echo 
$zipfile->file();
?>
  #7 (permalink)  
Antiguo 26/11/2013, 13:25
 
Fecha de Ingreso: mayo-2003
Mensajes: 523
Antigüedad: 20 años, 11 meses
Puntos: 6
Respuesta: Descargar archivos con PHP

Me agrada mucho la idea de zipear todas las fotos y que el cliente solo tenga que descargar un archivo. Estuve unas horas intentando crear el archivo zip pero hasta acá no lo conseguí. Voy a probar tu código Dalam, luego les cuento si logro el objetivo... Gracias a todos por las respuestas.
  #8 (permalink)  
Antiguo 29/11/2013, 16:32
 
Fecha de Ingreso: mayo-2003
Mensajes: 523
Antigüedad: 20 años, 11 meses
Puntos: 6
Respuesta: Descargar archivos con PHP

Uh Dalam un genio, me funciono al primer intento, muchisimas gracias!

Etiquetas: mysql, select, sql, tabla
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 14:55.