Я бы начал с этого ответа и вместо того, чтобы поместить результат вывода в строку, запишите буфер в TFileStream.
WinInet действительно хорош, так как он уважаетнастройки прокси, которые пользователь установил в Windows (так что вам не нужно много работать над тем, чтобы сделать это настраиваемым с помощью Indy).
Редактировать:
Я немного изменил этот ответ, чтобы загрузить двоичные файлы.
Поскольку он использует WinInet, вы можете использовать его как для загрузки по ftp, так и по http (да, я проверил, что это так).
Вы можете расширить это, чтобы использовать FtpFindFirstFile / InternetFindNextFile и чтение целой пачки файлов.
unit DownloadBinaryFileUnit;
interface
uses
Classes,
WinInet;
type
TWinInet = class
strict protected
class procedure ReadBinaryFileResponse(const UrlHandle: HINTERNET; const LocalFileName: string); static;
class procedure ReadResponse(const UrlHandle: HINTERNET; const ContentStream: TStream);
public
class procedure DownloadBinaryFile(const UserAgent, Url, LocalFileName: string); overload; static;
end;
implementation
uses
SysUtils,
Variants,
Windows,
IOUtils;
class procedure TWinInet.DownloadBinaryFile(const UserAgent, Url, LocalFileName: string);
var
InternetHandle: HINTERNET;
UrlHandle: HINTERNET;
begin
InternetHandle := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
try
UrlHandle := InternetOpenUrl(InternetHandle, PChar(Url), nil, 0, 0, 0);
try
ReadBinaryFileResponse(UrlHandle, LocalFileName);
finally
InternetCloseHandle(UrlHandle);
end;
finally
InternetCloseHandle(InternetHandle);
end;
end;
class procedure TWinInet.ReadBinaryFileResponse(const UrlHandle: HINTERNET; const LocalFileName: string);
var
ContentStream: TFileStream;
begin
ContentStream := TFile.Create(LocalFileName);
try
ReadResponse(UrlHandle, ContentStream);
finally
ContentStream.Free;
end;
end;
class procedure TWinInet.ReadResponse(const UrlHandle: HINTERNET; const ContentStream: TStream);
var
Buffer: array[0..1023] of Byte;
BytesRead: Cardinal;
begin
repeat
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
ContentStream.Write(Buffer, BytesRead);
until BytesRead = 0;
end;
end.
- jeroen