2009-08-04 13 views

risposta

28

Con l'aiuto dei componenti TMemoryStream e Indy.

uses 
    GIFImg; 

procedure TForm1.btn1Click(Sender: TObject); 
var 
    MS : TMemoryStream; 
    GIf: TGIFImage; 
begin 
    MS := TMemoryStream.Create; 
    GIf := TGIFImage.Create; 
    try 
    IdHTTP1.get('http://www.google.com/intl/en_ALL/images/logo.gif',MS); 
    Ms.Seek(0,soFromBeginning);  
    Gif.LoadFromStream(MS); 
    img1.Picture.Assign(GIF); 

    finally 
    FreeAndNil(GIF); 
    FreeAndNil(MS); 
    end; 
end; 
+0

Si potrebbe anche fare a meno di TGifImage e fare img1.Picture.LoadFromStream (MS); –

+1

** Attenzione: ** Se c'è un'eccezione in 'TIdHTTP.Get', allora questo codice libererà la variabile' GIF' non inizializzata. Non utilizzare le variabili in una sezione "finally" se non le hai inizializzate * prima * inserendo la corrispondente sezione "try". –

+1

No, Lars, non puoi farlo. 'TPicture.LoadFromStream' è protetto, non pubblico. Inoltre, chiama semplicemente 'Bitmap.LoadFromStream', quindi non saprà comunque come caricare i dati GIF. –

3

Codice elaborato anche per JPEG.

+0

Aggiungi "usa JPEG", ho fatto il mio esempio con l'unità GIF, è necessario utilizzare Jpeg uno. –

+0

Greener, non hai usato il giusto metodo 'Get'. Se si desidera riempire uno stream, è necessario ricordare di passare lo stream come parametro. La versione a un argomento di "Get" restituisce il contenuto della risorsa come una stringa nel valore di ritorno della funzione. –

+0

Sì Rob, Ho trovato il mio errore. Grazie ancora a tutti per l'aiuto. – Greener

0

Per this project Ho usato i componenti di Indy (come prima risposta), ma usando il codice all'interno di una discussione. Utile per scaricare immagini grandi o un gran numero di immagini. Puoi vedere la spiegazione completa del progetto nel link (è in spagnolo ma puoi usare la traduzione automatica).

In questo caso lo uso per scaricare tutte le immagini from this page.
Qui utilizzo un altro componente IdSSL:TIdSSLIOHandlerSocket, necessario per accedere a un URL https; Se è necessario accedere a un , non è necessario.

(commenti in inglese aggiunto)

Il codice di TDownImageThread è:

{: Clase para descargar una imagen y almacenarla en disco.} 
    {: Class to download image and save to disk} 
    TDownImageThread = class(TThread) 
    private 
    FURLImage: string; 
    FPathImage: string; 
    FFileNameImage: string; 
    // Internas 
    ImageName: string; 
    PathURL: string; 
    // Componente 
    idH:TidHTTP; 
    IdSSL:TIdSSLIOHandlerSocket; 
    public 
    // redefinir métodos // redefine methods 
    constructor Create(AURL:string; AOutPathImages:string); 
    destructor Destroy; override; 
    procedure Execute; override; 
    {: URL de la imagen a descargar. // URL to download} 
    property URLImage:string read FURLImage write FURLImage; 
    {: Path de disco local donde voy a almacenar la imagen.} 
    {: Local path to save the images} 
    property PathImage:string read FPathImage; 
    {: Nombre completa (path+Nombre) de la imagen almacenada en disco local} 
    {: complete name (path+name) of loval image} 
    property FileNameImage:string read FFileNameImage; 
    end; 



.... 


{ TDownImageThread } 
constructor TDownImageThread.Create(AURL, AOutPathImages: string); 
var 
    URI:TidURI; 
begin 

    // crear el thread suspendido // Create suspended thread 
    inherited Create(True); 
    // Parámetros: URL y dir de salida // Params URL and output dir. 
    Self.FURLImage := AURL; 
    Self.FPathImage := AOutPathImages; 
    // Crear con URL // create with URL 
    URI := TidURI.Create(AURL); 
    try 
    ImageName := URI.Document; 
    PathURL := URI.Path; 
    finally 
    URI.Free; 
    end; 
end; 

destructor TDownImageThread.Destroy; 
begin 
    inherited; 
end; 

//: recupara la imagen y la guarda en disco 
procedure TDownImageThread.Execute(); 
var 
    Stream:TFileStream; 
    IdH:TidHTTP; 
    IdSSL:TIdSSLIOHandlerSocket; 
    path:string; 
    dir:string; 
begin 
    // Directorio de salida // output directory 
    dir := AnsiReplaceText(PathURL, '/', STR_EMPTY); 
    // Nombre vacío // empty name 
    if (ImageName = STR_EMPTY) then begin 
    Exit; 
    end; 
    // Path de salida  // output path 
    path := IncludeTrailingBackslash(IncludeTrailingBackslash(PathImage) + 
      dir) + ImageName; 
    // Crearlo por si no existe // create it if not exist 
    ForceDirectories(ExtractFilePath(path)); 
    try 
    // Stream para la imagen // Stream for the image 
    Stream := TFileStream.Create(path, fmCreate); 
    try 
     // Crear componente para acceder /// Create the component in runtime 
     IdH := TidHttp.Create(nil); 
     IdH.ReadTimeout := 30000; 
     // necessary to use HTTPS 
     IdSSL := TIdSSLIOHandlerSocket.Create(nil); 
     IdH.IOHandler := IdSSL; 
     IdSSL.SSLOptions.Method := sslvTLSv1; 
     IdSSL.SSLOptions.Mode := sslmUnassigned; 
     idH.HandleRedirects := True; 
     IdH.RedirectMaximum := 3; 

     // proteccion 
     try 
     // Obtener la imagen // get the image 
     IdH.Get(Trim(FURLImage), Stream); 
     except 
     // Error al descargar la imagen 
     //.. Volcarlo al log 
     end; 
    finally 
     // Liberar // Free component 
     idH.Free; 
     // IdSSL.Free; 
     Stream.Free; 
    end; 
    // Path de salida  // output path 
    FFileNameImage := path; 
    except 
    // error al crear el fichero // error on create file 
    //... Log 
    end; 
end; 

Per utilizzarla, la chiamata è simile a questo:

// Crear un nuevo thread para descargar la imagen 
// Create a new thread LINK+output path 
th := TDownImageThread.Create(mmLinks.Lines[i], pathImages); 
// Procedimiento de retorno al finalizar 
// procedure to return on thread finalize 
th.OnTerminate := TerminateThread; 
th.Resume; 
0

meglio utilizzare questa funzione per il download:

function DownloadFile(Url, DestFile: string): Boolean; 
begin 
    try 
    Result := UrlDownloadToFile(nil, PChar(Url), PChar(DestFile), 0, nil) = 0; 
    except 
    Result := False; 
    end; 
end; 
Problemi correlati