TidHTTP; Descargar imágenes de una Web
Haciendo pruebas con el componente TidHTTP me ha surgido este ejemplo y me parece interesante mostrar el proceso completo que he seguido para descargar contenido desde una web. En este caso he accedido a las imágenes en formato PNG, pero es extensible a cualquier otros contenidos.
En un primer paso se trata de obtener el contenido (source) desde una página web y a partir de ahí, extraer los links (en mi caso correspondientes a imágenes en formato PNG) y descargar los ficheros para almacenarlos en disco. Para ello utilizaremos el control TidHTTP de la Indy.
Para obtener el código fuente de la página podemos utilizar un código como este:
// URL de la página StrURL := ... ; // Crear componente para acceder IdH := TIdHTTP.Create(nil); // proteccion para liberar try // proteccion por error try // Obtenemos la pagina Resp := IdH.Get(Trim(StrURL)); // recuperamos la respuesta TSContent.Text := Resp; except on E:Exception do begin MessageDlg('Error al acceder a la página. '+#13+#10+ 'Mensaje: ' + E.Message, mtError, [mbOK], 0); end; end; // try finally IdH.Free; end; |
Una vez que obtenemos la respuesta del componente almacenamos el contenido de la página en un TStrings. Si accedemos a la página: http://neftali.clubdelphi.com/temporal/ejemplo1.html
Obtendremos como resultado del Get el siguiente texto, que corresponde al código fuente de la página:
Lo siguiente que vamos a hacer es un simple «parseo» buscando los enlaces que nos interesen. En nuestro ejemplo queremos links a imágenes en formato png. Utilizando funciones de la clase SysUtils podemos obtener sin mayor problemas los links contenidos en el código; Si probáis con la página de ejemplo, deberíais obtener un único link:
http://neftali.clubdelphi.com/images/GLibWMI_paleta_1.8b.png
Por último, nos queda ver el código necesario para descargar la imagen y almacenarla en disco. Para ello podemos utilizar de nuevo el componente TidHTTP. En mi caso, y en previsión de que pueda haber varias imágenes a descargar, he creado una clase derivada de TThread para ello:
{: Clase para descargar una imagen y almacenarla en disco.} TDownImageThread = class(TThread) private FURLImage: string; FPathImage: string; FFileNameImage: string; // Internas ImageName: string; PathURL: string; // Componente idH:TidHTTP; public // redefinir métodos constructor Create(AURL:string; AOutPathImages:string); destructor Destroy; override; procedure Execute; override; {: URL de la imagen a descargar. } property URLImage:string read FURLImage write FURLImage; {: Path de disco local donde voy a almacenar la imagen.} property PathImage:string read FPathImage; {: Nombre completa (path+Nombre) de la imagen almacenada en disco local} property FileNameImage:string read FFileNameImage; end; |
Al crear el Thread (método Create) ya pasamos como parámetros, la URL de la imagen a descargar y el Directorio inicial donde se van a guardar las imágenes encontradas.
El método Execute creamos un componente TidHTTP (igual a como lo hemos hecho antes), pero en este caso utilizamos un TFileStream para recoger el fichero que descargamos y almacenarlo en disco.
Utilizamos el Path de la URL para generar diferentes directorios para las diferentes imágenes:
···················································································································
URL: http://neftali.clubdelphi.com/images/GLibWMI_paleta_1.8b.png
Path: images
FileName: GLibWMI_paleta_1.8b.png
···················································································································
//: recupara la imagen y la guarda en disco procedure TDownImageThread.Execute(); var Stream:TFileStream; IdH:TidHTTP; path:string; dir:string; begin // Directorio de salida dir := AnsiReplaceText(PathURL, '/', STR_EMPTY); // Nombre vacío if (ImageName = STR_EMPTY) then begin Exit; end; // Path de salida path := IncludeTrailingBackslash(IncludeTrailingBackslash(PathImage) + dir) + ImageName; // Crearlo por si no existe ForceDirectories(ExtractFilePath(path)); try // Stream para la imagfen Stream := TFileStream.Create(path, fmCreate); try //recuperar la imagen IdH := TidHTTP.Create(nil); IdH.AllowCookies := True; // proteccion try IdH.Get(Trim( FURLImage), Stream); except // Error al descargar la imagen //.. Volcarlo al log end; finally // Liberar idH.Free; Stream.Free; end; // Path de salida FFileNameImage := path; except // error al crear el fichero //... Log end; end; |
El resultado se puede ver en este ejemplo.
Una vez descargadas las imágenes se muestran en un componente en la misma aplicación, y desde ahí podemos acceder a la información de la imagen y realizar algunas acciones sobre ellas.
Para realizar pruebas podéis introducir, por ejemplo direcciones como:
- URL de una entrada de este mismo blog (Acceder a GRUB desde Windows)
- URL con la lista de Iconos de Google Maps.
- URL de prueba que hemos utilizado más arriba.
- …
Como siempre podéis descargar los fuentes y los binarios de ejemplos.
ACTUALIZACIÓN (26/02/2015): La página del ejemplo ha cambiado y ahora se accede por https. por lo tanto el enlace es:
https://sites.google.com/site/gmapsdevelopment/Home
Por lo tanto para poder descargar tanto la página inicial (de donde se extraen los enlaces), como las imágenes en si, hay que modificar ligeramente el programa.
Hay que utilizar el componente TIdSSLIOHandlerSocket para poder utilizar SSL y añadir al proyecto as librerías de acceso a SSL.
No hay muchas modificaciones en el código, pero si queréis verlas, dejaré el código antiguo y el nuevo (compilado en Delphi 7) para que podáis compararlos.
<DESCARGAR BINARIO v2 + DLL ssl>
<DESCARGAR DLL’s para acceder SSL>
NOTA: Para generar las imágenes en disco PNG he utilizado el componente “Portable Network Graphics Delphi” de Gustavo Huffenbacher Daud, que podéis encontrar y descargar de forma gratuita de Internet.
Un saludo.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…