TIdHttp(Indy10)を使用して単純なhttpダウンローダーを実装したいと思います。インターネットから2種類のコード例を見つけました。残念ながら、それらのどれも私を100%満足させません。これがコードです。アドバイスが必要です。
バリアント1
var
Buffer: TFileStream;
HttpClient: TIdHttp;
begin
Buffer := TFileStream.Create('somefile.exe', fmCreate or fmShareDenyWrite);
try
HttpClient := TIdHttp.Create(nil);
try
HttpClient.Get('http://somewhere.com/somefile.exe', Buffer); // wait until it is done
finally
HttpClient.Free;
end;
finally
Buffer.Free;
end;
end;
コードはコンパクトで非常に理解しやすいです。問題は、ダウンロードの開始時にディスク領域が割り当てられることです。もう1つの問題は、コードがバックグラウンドスレッドで実行されない限り、GUIでダウンロードの進行状況を直接表示できないことです(または、HttpClient.OnWorkイベントをバインドできます)。
バリアント2:
const
RECV_BUFFER_SIZE = 32768;
var
HttpClient: TIdHttp;
FileSize: Int64;
Buffer: TMemoryStream;
begin
HttpClient := TIdHttp.Create(nil);
try
HttpClient.Head('http://somewhere.com/somefile.exe');
FileSize := HttpClient.Response.ContentLength;
Buffer := TMemoryStream.Create;
try
while Buffer.Size < FileSize do
begin
HttpClient.Request.ContentRangeStart := Buffer.Size;
if Buffer.Size + RECV_BUFFER_SIZE < FileSize then
HttpClient.Request.ContentRangeEnd := Buffer.Size + RECV_BUFFER_SIZE - 1
else
HttpClient.Request.ContentRangeEnd := FileSize;
HttpClient.Get(HttpClient.URL.URI, Buffer); // wait until it is done
Buffer.SaveToFile('somefile.exe');
end;
finally
Buffer.Free;
end;
finally
HttpClient.Free;
end;
end;
最初にサーバーからファイルサイズを照会し、次にファイルの内容を分割してダウンロードします。取得したファイルの内容は、完全に受信されるとディスクに保存されます。潜在的な問題は、サーバーに複数のGETリクエストを送信する必要があることです。一部のサーバー(megauploadなど)が特定の期間内のリクエスト数を制限する可能性があるかどうかはわかりません。
私の期待
- ダウンローダーは、サーバーにGETリクエストを1つだけ送信する必要があります。
- ダウンロードの開始時にディスク容量を割り当てないでください。
ヒントは大歓迎です。