|
メニュー
アンテナ
|
[Delphi] 簡単に http 非同期ファイル取得を行うには概要
そうはならない非同期関数もあるのだが,これらは扱いが煩雑で,Delphi にも実装例はあるものの,同期式のときとは比較にならないほどのコーディングを 要求される。 ここでは,その コードHTTPSyncFileDownloaderThread.pas unit HTTPSyncFileDownloaderThread;
interface
uses
Classes, Windows, SysUtils, WinInet, Forms;
type
THTTPSyncFileDownloader = class(TThread)
private
UserAgent, URL, Headers: String;
LastModified: TDateTime;
protected
procedure Execute; override;
public
stream: TStream;
constructor Create(aUserAgent, aURL, aHeaders: String;
pfnCallback: TNotifyEvent; aStream: TStream); overload;
end;
implementation
// THTTPSyncFileDownloader
procedure THTTPSyncFileDownloader.Execute;
var
hSession: HINTERNET;
hService: HINTERNET;
lpBuffer: array[0..1024] of Byte;
dwBytesRead: DWORD;
szHeader: string;
dwSize, Reserved: DWORD;
ft1, ft2: FILETIME;
httpLastModified: TSystemTime;
begin
inherited;
hSession := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
try
if Assigned(hSession) then
begin
szheader := Headers;
SetLength(szHeader, Length(szHeader));
hService := InternetOpenUrl(hSession, PChar(URL), PChar(szHeader), $ffffffff,
INTERNET_FLAG_RELOAD, 0);
try
if Assigned(hService) then
begin
dwBytesRead := 1024;
while dwBytesRead = 1024 do
begin
// 同期モードのため,InternetReadFile() は,
// データがまだ来ていないときには待ち続ける。
// そのため,dwBytesRead
// 理由が何であれダウンロードが終了したと
// 考えることができる。
InternetReadFile(hService, @lpBuffer, 1024, dwBytesRead);
stream.WriteBuffer(lpBuffer, dwBytesRead);
Sleep(10);
end;
// touch. 必要なければ削除しても良い。
dwSize := sizeof(httpLastModified);
Reserved := 0;
HttpQueryInfo(hService, HTTP_QUERY_LAST_MODIFIED or HTTP_QUERY_FLAG_SYSTEMTIME,
@httpLastModified, dwSize, Reserved);
SystemTimeToFileTime(httpLastModified, ft2);
FileTimeToLocalFileTime(ft2, ft1); // かなり適当
FileTimeToSystemTime(ft1, httpLastModified);
LastModified := SystemTimeToDateTime(httpLastModified);
// touch ここまで
end;
finally
InternetCloseHandle(hService);
end;
end;
finally
InternetCloseHandle(hSession);
end;
end;
constructor THTTPSyncFileDownloader.Create(aUserAgent, aURL, aHeaders: String;
pfnCallback: TNotifyEvent; aStream: TStream);
begin
inherited Create(false);
FreeOnTerminate := true;
UserAgent := aUserAgent;
URL := aURL;
Headers := aHeaders;
OnTerminate := pfnCallback;
stream := aStream;
end;
end.
解説
このスレッドは,コンストラクタ コンストラクタ ソースコード中で 注意このコードは実用的なコードになるためのいくつかの要素を省略している。たとえば,
データ取得ループでは 出典monazilla.org(w の WinINet サンプル
を改変した,auROra のソースコード
|