Загрузка файла в Delphi

В поисковой системе Google показано несколько примеров того, как загрузить файл в Delphi, но большинство из них ошибочно, а половина времени не работает в моем опыте.

Я ищу простое надежное решение, которое позволит мне загрузить один exe (для обновления моего приложения) и будет удерживать выполнение текущего потока обновлений до тех пор, пока загрузка не будет выполнена или ошибки не исчезнут. Процесс уже имеет резьбу, поэтому код загрузки должен выполняться до тех пор, пока он не будет выполнен (надеюсь).

Здесь две реализации, кажущиеся очень сложными   1. http://www.scalabium.com/faq/dct0116.htm
  2. http://delphi.about.com/od/internetintranet/a/get_file_net.htm

Ответ 1

Второй подход - это стандартный способ использования интернет-ресурсов с использованием WinINet, входящего в состав Windows API. Я использовал его много, и он всегда работал хорошо. Первый подход, который я никогда не пробовал. (Ни один из них не является "очень сложным". При использовании Windows API всегда будет несколько дополнительных шагов.)

Если вам нужен очень простой метод, вы можете просто вызвать UrlMon.URLDownloadToFile. Вы не получите никакого контроля (вообще!) О загрузке, но это очень просто.

Пример:

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

Ответ 2

Почему бы не использовать indy. Если вы используете TIdHTTP, простую

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;

Вы даже можете добавить индикатор выполнения с помощью событий OnWork и OnWorkBegin

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;

Я не уверен, что это пожар событий в контексте основного потока, поэтому любые обновления, сделанные для компонентов VCL, возможно, придется выполнять с использованием компонента tidnotify для проблем с потоками aviod. Может быть, кто-то еще может это проверить.