Foros del Web » Programando para Internet » PHP »

Bajar archivos desde el servidor via HTTP

Estas en el tema de Bajar archivos desde el servidor via HTTP en el foro de PHP en Foros del Web. Hola a todos... En esta oportunidad necesito bajarme archivos via HTTP de un servidor. Son imágenes de no más de 400 bytes. Por ejemplo: http://www.handyzone.com/galerias/logos/amor/ ...
  #1 (permalink)  
Antiguo 20/09/2003, 09:34
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Pregunta Bajar archivos desde el servidor via HTTP

Hola a todos...

En esta oportunidad necesito bajarme archivos via HTTP de un servidor. Son imágenes de no más de 400 bytes. Por ejemplo:

http://www.handyzone.com/galerias/logos/amor/

En dicha carpeta hay unas 200 imagenes (pueden acceder y verlas), pero guardarlas todas a mano es imposible.

¿Qué función puedo usar en PHP para descargarme dichas imagenes a mi PC?

Saludos y gracias.
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #2 (permalink)  
Antiguo 20/09/2003, 14:13
Ex Colaborador
 
Fecha de Ingreso: junio-2002
Mensajes: 9.091
Antigüedad: 22 años, 5 meses
Puntos: 16
Hola,

Muy sencillo. Hablas con el dueño de la web y se las pides. Tambien puedes pedirle que te las ponga en una carpeta accesible desde FTP, te cree una cuenta, y si tu PHP tiene soporte FTP, bajartelas asi.

Via HTTP es mas dificil. Podrias usar fopen() si tienes activados los fopen wrappers (www.php.net/wrappers) para guardarlas. Eso si, necesitas saber el nombre de los ficheros.

Por supuesto, supongo que tendras el permiso del dueño de las imagenes para hacerlo. Porque si no, podrias estar violando leyes de derechos de autor y demas. No todo lo que esta en internet es para que cualquiera lo use.

Saludos.
__________________
Josemi

Aprendiz de mucho, maestro de poco.
  #3 (permalink)  
Antiguo 20/09/2003, 15:57
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 21 años, 4 meses
Puntos: 1
Hola,

Parece que lo que buscas es una especie de crawler o programa de descargas automatizado, que pueda ser usado para obtener imágenes enlazadas desde una determinada página web. Un ejercicio interesante.

En tal caso, se me ocurre que puede implementarse algo como esto:


Código:
<?php

/*** Variables de control del script ***/

// URL de la pagina web de donde se van a descargar archivos

$url = 'http://www.handyzone.com/galerias/logos/amor/';


// Extensiones usadas para reconocer el tipo de archivos a descargar

$extensiones = array ('jpg', 'gif', 'png');


// Directorio local en donde se guardaran los archivos. Note que esta
// ruta debe terminar en el caracter delimitador de directorios del
// sistema operativo (barra en Unix, o barra invertida en windows, por
// ejemplo). Asegurese de que este directorio tenga los permisos
// apropiados para que este script pueda crear archivos alli.

$directorio = './imagenes/';



/*** Funciones ***/

function descargar_archivo ($url)
{
    $bufer = '';

    if (ini_get ('allow_url_fopen')) {

        // La forma facil...

        $da = fopen ($url, 'r');

        if (! $da) {
            echo "No ha podido leerse el contenido de $url\n";
            return FALSE;
        }

        while (! feof ($da))
            $bufer .= fread ($da, 4096);

        fclose ($da);
    } else {

        // Bueno, tendremos que obtener el archivo remoto directamente
        // mediante comunicacion al nivel de sockets... Nada
        // particularmente complejo despues de todo

        preg_match ('/^\\s*(?:\\w+:\\/{2})?(.*?)(:\\d+)?(\\/.*)$/',
                    $url, $coincidencias);

        $dominio = $coincidencias[1];
        $puerto  = $coincidencias[2];
        $ruta    = $coincidencias[3];

        if (! $puerto)
            $puerto = '80';

        if (! $ruta)
            $ruta = '/';

        $socket = fsockopen ($dominio, $puerto);

        if (! $socket) {
            echo "No pudo establecerse una conexion con $dominio\n";
            return FALSE;
        }

        fwrite ($socket, "GET $ruta HTTP/1.0\n\n");

        while (! feof ($socket))
            $bufer .= fread ($socket, 4096);

        fclose ($socket);

        $bufer = preg_replace ('/^.*?(\\r?\\n){2}/s', '', $bufer);
    }

    return $bufer;
}



/*** Programa principal ***/

echo "<pre>\n";

$documento = descargar_archivo ($url);

if (! $documento)
    exit (1);


// Buscar las etiquetas que crean enlaces hacia otros documentos

preg_match_all ('/<\\s*a\\s+.*?\\bhref=[\'"]?([^\'"\\s>]*)/i',
                $documento, $coincidencias);

$secuencia = $extensiones[0];
for ($i = 1, $conteo = count ($extensiones); $i < $conteo; $i++)
    $secuencia .= '|' . $extensiones[$i];

foreach ($coincidencias[1] as $enlace) {
    if (! preg_match ('/\\.(' . $secuencia . ')$/i', $enlace))
        continue;

    $archivo = preg_replace ('/^.*\\//', '', $enlace);

    if ($enlace{0} == '/') {

        preg_match ('/^\\s*(?:\\w+:\\/{2})?([^\\/]*)/', $url, $coincidencias);
        $enlace_url = $coincidencias[1] . $enlace;

    } else if (preg_match ('/^\\s*\\w+:\\/{2}/', $enlace))
        $enlace_url = $enlace;

    else {
        preg_match ('/^.*\\//', $url, $coincidencias);

        if ($coincidencias[0])
            $enlace_url = $coincidencias[0] . $enlace;
        else
            $enlace_url = $url . '/' . $enlace;
    }

    echo "Descargando $enlace_url ..";

    $contenido = descargar_archivo ($enlace_url);

    if (! $contenido) {
        echo "No pudo descargarse el documento $enlace_url\n";
        continue;
    }

    $da = fopen ("$directorio$archivo", 'w');

    if (! $da) {
        echo "No pudo crearse el archivo $archivo en el disco local\n";
        continue;
    }

    fwrite ($da, $contenido);

    fclose ($da);

    echo "listo\n";
}

echo "</pre>\n";

?>

No lo he probado exhaustivamente, y quizás cometí algún error en alguna parte del código, pero al menos parece obtener el resultado que buscas. :)


Un cordial saludo
  #4 (permalink)  
Antiguo 20/09/2003, 23:57
 
Fecha de Ingreso: mayo-2003
Ubicación: Cuernavaca, Mor.
Mensajes: 117
Antigüedad: 21 años, 6 meses
Puntos: 2
no olviden avisar si encuentras eso!

Última edición por vic_mx; 20/09/2003 a las 23:59
  #5 (permalink)  
Antiguo 22/09/2003, 05:41
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Buenas.

Tengo todos los permisos para descargar los archivos, el asunto es que el dueño me dijo que los descargara usando PHP porque él se encuentra de viaje y no se puede conectar a la red.

Además, si hago eso, quizás ese mismo señor me dé trabajo en su empresa. Por lo tanto debo hacerlo.

Yo tengo los nombres de las imágenes, son números.
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #6 (permalink)  
Antiguo 22/09/2003, 13:01
Ex Colaborador
 
Fecha de Ingreso: junio-2002
Mensajes: 9.091
Antigüedad: 22 años, 5 meses
Puntos: 16
Bien, entonces prueba el codigo de leonardop, la segunda parte, ya que si sabes el nombre de los ficheros y la ruta, no necesitas sacar los links de una pagina.

Suerte.
__________________
Josemi

Aprendiz de mucho, maestro de poco.
  #7 (permalink)  
Antiguo 22/09/2003, 20:52
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Exelentes clases de expresiones regulares que nos dá leonardop .. xDDDD... ¿para cuando un mini tutorial de exp.reg aplicado a PHP? ..

Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #8 (permalink)  
Antiguo 09/10/2003, 20:25
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Ok... haciendo pruebas llegué a esto:

Código PHP:
<?php
$archivo 
file_get_contents('http://www.handyzone.com/galerias/logos/amor/1028.gif');
echo 
$archivo;
?>
Eso almacena el archivo en una variable, y luego cuando hago un echo, me muestra la imagen perfectamente.

¿Pero cómo hago para guardar dicha imagen en mi disco duro?

Estuve probando con fwrite() pero no me funcionó. ¿Qué hago?
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #9 (permalink)  
Antiguo 10/10/2003, 07:48
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Tienes que usar fwrite() .. pero antes debes usar fopen() en modo binario ("rb") ...


Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #10 (permalink)  
Antiguo 10/10/2003, 07:55
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
¿O sea... debo dejar de usar file_get_contents() y abrir el archivo usando fopen() y luego escribirlo usando fwrite()?
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #11 (permalink)  
Antiguo 10/10/2003, 09:01
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Código PHP:
<?php
// lees tu archivo remoto ..
$url='http://www.handyzone.com/galerias/logos/amor/1028.gif';
$fp fopen($url,'rb');
$archivo fread ($fpfilesize ($url));

// GUARDAS tu $archivo (variable)
$fp=fopen('imagen_remota.gif','w');  // abrir archivo en modo binario "rb" ..
fwirte($fp,$archivo); // escribir ...
fclose($fp); // cerrar archivo ..
?>
El problema es que filesize() NO devuelve valor en llamadas externas (que pasen por http:// ) sólo en locales (archivo.tal directo) .. Si conoces el tamaño (en bytes) de ese archivo .. puedes indicarlo en el segundo parámetro de fread() y fucionaría correctamente (en teoría).

Pero, con este código que simula una conexión HTTP normal .. puedes obtener el tamaño de un archivo remoto:

Créditos: http://www.iezzi.ch/snippets/003_fsize.php

(traducido a función):

Código PHP:
<?php

function filesize_externo($u){

$ourhead "";
$url=parse_url($u); 
$host=$url["host"]; 
$path=$url["path"]; 

$fp fsockopen($host80, &$errno, &$errstr20); 
if(!
$fp) { 
    echo(
"error"); 
    exit (); 
} else { 
    
fputs($fp,"HEAD $u HTTP/1.1\r\n"); 
    
fputs($fp,"HOST: dummy\r\n"); 
    
fputs($fp,"Connection: close\r\n\r\n"); 

    while (!
feof($fp)) { 
        
$ourhead sprintf("%s%s"$ourheadfgets ($fp,128)); 
    }

fclose ($fp);

$split_head explode("Content-Length: ",$ourhead);
$size round(abs($split_head[1])/1024);
return  
$size;
}
?>
Así que el código superior que te dejé tendrías que sustituir:

Código PHP:
$archivo fread ($fpfilesize ($url)); 
por

Código PHP:
$archivo fread ($fpfilesize_externo ($url)); 
Y .. debería ir. Ya nos contaras.

Un saludo,



Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.

Última edición por Cluster; 10/10/2003 a las 09:29
  #12 (permalink)  
Antiguo 10/10/2003, 09:13
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
El problema es que la "imagen_remota.gif" no existe y PHP deberá crearla. Por lo tanto me devuelve error.

Ese es mi problema principal, crear dicha imagen que no existe en mi PC usando el contenido obtenido vía fread() o file_get_contents().

Saludos.
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #13 (permalink)  
Antiguo 10/10/2003, 09:29
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Me equivoqué ...

// GUARDAS tu $archivo (variable)
$fp=fopen('imagen_remota.gif','rb');

debe ser:

$fp=fopen('imagen_remota.gif','w');

En modo esritura .. Si no existe el archivo .. lo crea.

Más info de modos de lectura/escritura:
http://www.php.net/fopen

Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #14 (permalink)  
Antiguo 10/10/2003, 09:30
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Ahh !!!.. el problema estaba en el "rb" del fopen() de imagen_remota.gif. Si en lugar de colocar "rb" colocamos "wb", entonces el fichero se crea solo usando el contenido que posee fread().

"rb" es lectura en modo binario, pero si lo que deseamos es crear un archivo nuevo en nuestro PC, entonces deberemos colocar "wb" lo que significa escritura en modo binario.

Código PHP:
$url='http://www.handyzone.com/galerias/logos/amor/1028.gif';
$fp fopen($url,'rb');
$archivo fread ($fp400);

$fp=fopen('imagen_remota.gif','wb');
fwrite($fp,$archivo);
fclose($fp); 
Y listo, usando un while() podemos descargar archivos desde un servidor remoto. Esto va para las FAQS.
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #15 (permalink)  
Antiguo 10/10/2003, 09:53
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Esperaa! drcyber

usas en el fread() un tamaño fijo .. 400 bytes para ser exactos. Mejor usa la funcion que puse filesize_externo() para ver exactamente el tamaño de la imagen (o archivo en general). Fijate por ejemplo si tengo imagenes más pesadas .. tu sólo leerias esos primeros 400 bytes ..

Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #16 (permalink)  
Antiguo 10/10/2003, 10:02
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Bueno... en mi caso... todas las imágenes son de 398 bytes. Lo coloqué en 400 bytes para dar un margen de error.

Thankz anyway.
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #17 (permalink)  
Antiguo 10/10/2003, 10:27
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Intenté descargar las imágenes asi:

Código PHP:
for($i=1$i<=3000$i++){
    
$url="http://www.handyzone.com/galerias/logos/amor/$i.gif";
    if(
file_exists($url)){
        
$fp fopen($url,'rb');
        
$archivo fread ($fp400);
        
$fp=fopen($i.'.gif','wb');
        
fwrite($fp,$archivo);
        
fclose($fp);
        
$escr++;
    }

Pero entonces la función file_exist() siempre me devuelve false. Lo cual es erróneo, porque los archivos existen.

Tengo algo malo en $url ???
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #18 (permalink)  
Antiguo 10/10/2003, 10:39
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Mira bien la documentación de PHP sobre esa función ...

file_exist sólo funciona en "local" no en remoto ...

Por eso, si usas la función que te puse que mira el tamaño del archivo haciendo una conexión HTTP directa por sockets podrías ver si el el tamaó es mayor que 0 byte y ademas ajustar correctamente el valor del archivo que estás generando ...

Unos "bytes" de más .. si editas la imagen veras "negro" (o no sale corecto) (haz la prueba y lee muchos más bytes de los que sabes que tienen ..

Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #19 (permalink)  
Antiguo 10/10/2003, 11:23
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Pues... me da un error en el

$fp = fsockopen($host, 80, &$errno, &$errstr, 20);

Warning: Call-time pass-by-reference has been deprecated - argument passed by value; If you would like to pass it by reference, modify the declaration of fsockopen(). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file. However, future versions may not support this any longer. in c:\appserv\www\logos\amor\index.php on line 10


¿?
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #20 (permalink)  
Antiguo 10/10/2003, 11:55
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Quita los & a esas variables y prueba ..

Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #21 (permalink)  
Antiguo 10/10/2003, 19:01
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Nop... ahora me devuelve:

Fatal error: Maximum execution time of 30 seconds exceeded in c:\appserv\www\logos\amor\index.php on line 20

Linea 20: $ourhead = sprintf("%s%s", $ourhead, fgets ($fp,128));

Se complicó la cosa hombre.

¿No hay una forma de verificar si el archivo existe remotamente con file_exists() o algo similar?
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #22 (permalink)  
Antiguo 10/10/2003, 22:11
Avatar de sdf23  
Fecha de Ingreso: diciembre-2002
Mensajes: 297
Antigüedad: 21 años, 11 meses
Puntos: 0
me tome la libertad de hacerlo, funciona el script por que ya lo probe 140 imagenes en menos de 1 minutos :D ahi va el codigo:
Código PHP:
<?
set_time_limit
(0);
function 
caga($return)
{
    
copy("http://www.handyzone.com/galerias/logos/amor/".$return.".gif","amor/".$return.".gif");
}
$fd fopen ("http://www.handyzone.com/galerias/logos/amor/""r");
while (!
feof($fd)) {
    
    
$buffer fgets($fd4096);
    
$buffer preg_replace("/<a href=\"(.*)\.gif\">/esiU","caga('leer abajo')",$buffer);
    
//echo $buffer;
}
fclose ($fd);
?>
donde dice "leer abajo" sustituyelo por \\1
debes crear una carpeta llamada "amor"
__________________

la vida es bella cuando no es culera

Última edición por sdf23; 10/10/2003 a las 22:13
  #23 (permalink)  
Antiguo 10/10/2003, 22:16
Avatar de sdf23  
Fecha de Ingreso: diciembre-2002
Mensajes: 297
Antigüedad: 21 años, 11 meses
Puntos: 0
lo mas facil un fopen, y luego un copy :D:D
__________________

la vida es bella cuando no es culera
  #24 (permalink)  
Antiguo 11/10/2003, 00:10
Avatar de nuevo  
Fecha de Ingreso: mayo-2003
Ubicación: Spain
Mensajes: 2.009
Antigüedad: 21 años, 6 meses
Puntos: 2
si que es cafre si.... a ver ese tuto para las expresiones regurares... juas, juas... quiero aprender...
__________________
3w.valenciadjs.com
3w.laislatv.com
  #25 (permalink)  
Antiguo 11/10/2003, 06:25
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
Ok sdf23... el código trabaja... pero no lo entiendo muy bien. ¿Me lo explicas paso por paso?... disculpa la molestia, pero quiero aprender ... ;)
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
  #26 (permalink)  
Antiguo 11/10/2003, 13:41
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 22 años, 10 meses
Puntos: 129
Bueno .. el copy() para accesos remotos sólo funciona desde PHP 4.3.0 si mal no recuerdo (sólo como observación) ..

drcyber ..

El código que te pasé no lo hice yo .. es más ahí dejé la página del autor .. tampoco lo he probado así que no sé que sucede ahí.

Un saludo,
__________________
Por motivos personales ya no puedo estar con Uds. Fue grato haber compartido todos estos años. Igualmente los seguiré leyendo.
  #27 (permalink)  
Antiguo 11/10/2003, 21:20
Avatar de drcyber  
Fecha de Ingreso: julio-2002
Mensajes: 826
Antigüedad: 22 años, 3 meses
Puntos: 2
No hay problema Cluster. Voy a analizarlo bien.
__________________
Dr. Cyber
Ingeniarte.com
(soy el mismo Takitei)
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 22:27.