2010-08-17 10 views
11

Una ricerca su google mostra alcuni esempi su come scaricare un file in Delphi, ma la maggior parte sono bug e la metà delle volte non funziona nella mia esperienza.Download di un file in Delphi

Sto cercando una soluzione semplice e robusta che mi consenta di scaricare un singolo exe (per l'aggiornamento della mia app) e che manterrà l'esecuzione del thread di aggiornamento corrente fino a quando il download è terminato o errori. Il processo è già threadato, quindi il codice di download dovrebbe contenere l'esecuzione fino al completamento (si spera).

Ecco due implementazioni, entrambi sembrano molto complicato
1. http://www.scalabium.com/faq/dct0116.htm
2. http://delphi.about.com/od/internetintranet/a/get_file_net.htm

risposta

12

Il secondo approccio è il modo standard di utilizzo di risorse Internet utilizzando WinINet, una parte della API di Windows. L'ho usato molto, e ha sempre funzionato bene. Il primo approccio che non ho mai provato. (Né è "molto complicato". Ci sono sempre alcuni passaggi aggiuntivi quando si utilizza l'API di Windows.)

Se si desidera un metodo molto semplice, è sufficiente chiamare UrlMon.URLDownloadToFile. Non avrai alcun controllo preciso (del tutto!) Sul download, ma è molto semplice.

Esempio:

URLDownloadToFile(nil, 
        'http://www.rejbrand.se', 
        PChar(ExtractFilePath(Application.ExeName) + 'download.htm'), 
        0, 
        nil); 
+3

Suggerimento: sostituire 'Application.ExeName' con' ParamStr (0) 'per rimuovere la dipendenza dall'unità' Forms'. – mjn

+0

@mjustin: vero. Ma nel codice di produzione, non vorrete comunque salvare i file nella directory dell'applicazione, che è di sola lettura (Programmi), a meno che il programma non sia portatile (ad esempio, si esegue su una chiavetta USB). –

+0

Grazie per la risposta Andreas. Sono andato con il secondo approccio che ho postato dal momento che hai detto che era lo standard, si spera che si rivelasse affidabile. Grazie per i tuoi sforzi. – Daisetsu

16

Perché non fanno uso di Indy. Se si utilizza il TIdHTTP sua semplice

procedure DownloadFile;  
var 
    IdHTTP1: TIdHTTP; 
    Stream: TMemoryStream; 
    Url, FileName: String; 
begin  
    Url := 'http://www.rejbrand.se'; 
    Filename := 'download.htm'; 

    IdHTTP1 := TIdHTTP.Create(Self); 
    Stream := TMemoryStream.Create; 
    try 
    IdHTTP1.Get(Url, Stream); 
    Stream.SaveToFile(FileName); 
    finally 
    Stream.Free; 
    IdHTTP1.Free; 
    end; 
end; 

È anche possibile aggiungere una barra di avanzamento utilizzando l'OnWork e OnWorkBegin Eventi

procedure IdHTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode;AWorkCountMax: Int64); 
begin 
    ProgressBar.Max := AWorkCountMax; 
    ProgressBar.Position := 0; 
end; 

procedure IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64); 
begin 
    ProgressBar.Position := AWorkCount; 
end; 

non sono sicuro se questi incendi evento nel contesto dei principali thread, quindi eventuali aggiornamenti fatti ai componenti VCL potrebbero dover essere eseguiti utilizzando il componente tidnotify per problemi di threading aviod. Forse qualcun altro può controllarlo.

+1

Se il file è di grandi dimensioni, è possibile che si desideri utilizzare un flusso di file anziché uno stream di memoria. – MikeT