Deplhi TWebBrowser を使用してフォームに「ニュース」ページを表示したいと考えています。ニュース ページは、当社の Web サイトに随時アップロードする単純な HTML ページであり、さまざまなツールから出力される場合があります。表示は問題ありませんが、最後に表示してから変更されたかどうかをアプリで知りたいので、理想的には、変更された日付/時刻またはサイズ/チェックサムのいずれかを取得したいと考えています。精度は重要ではありません。理想的には、メモ帳などの HTML ファイルの編集に「単純な」ツールが使用されたため、失敗する可能性のあるプロパティに依存しないでください。Web で確認すると、いくつかのドキュメントが変更された Java 呼び出しがありますが、どこから始めればよいか本当にわかりません。私は、Delphi の Winapi の多数の呼び出しに目を通しました。WinInet ユニットと、HTTP でファイルを取得して調べることができるようですが、それはハンマーでクルミを割るように思えます。また、明らかな何かが欠けていると思わせるファイルの日時機能も表示されません。Delphi XE5 を使用しています。どの方向を見ればいいですか?ご指摘ありがとうございます。
2 に答える
IndyTIdHTTP
を使用してリクエストを送信し、/ヘッダーHEAD
を調べることができます。Last-Modified
Content-Length
例えば:
procedure TForm1.Button1Click(Sender: TObject);
var
Url: string;
Http: TIdHTTP;
LastModified: TDateTime;
ContentLength: Integer;
begin
Url := 'http://yoursite.com/newspage.html';
Http := TIdHTTP.Create(nil);
try
Http.Head(Url);
LastModified := Http.Response.LastModified;
ContentLength := Http.Response.ContentLength;
ShowMessage(Format('Last-Modified: %s ; Content-Length: %d', [DateTimeToStr(LastModified), ContentLength]));
finally
Http.Free;
end;
end;
TWebBrowser.DocumentComplete
イベントが発生したら、リクエストを作成し、変数HEAD
を保存LastModified
しContentLength
ます。次に、変更をテストするためのリクエストを定期的に作成します (たとえば、HEAD
経由で)。TTimer
これらのヘッダー パラメーターは Web サーバーの実装に依存し、サーバー上のファイル システムの日付/時刻を返さない場合があります (動的ページなど)。サーバーがこれらのパラメーターをまったく返さない場合があります。
たとえば、HTML
IIS の静的ページでは、必要なLast-Modified
ファイル システムの最終変更日時が返されます。
動的コンテンツ (例: php、asp、.NET など) の場合、Web サーバーを制御する場合はHTTP
、サーバー側に独自のカスタム応答ヘッダーを追加して、ファイル システムの日時 (例: X-Last-Modified
) または必要に応じて応答Last-Modified
ヘッダーを設定し、クライアント側でこのヘッダーを調べます。
HTTP コンテンツ全体を検査/ハッシュする必要がある場合は、GET
メソッド を発行する必要があります。http.Get(URL)
kobik、David、および TLama からの提案と指摘のおかげで、私は実際に大ハンマーが必要であることに気付き、最終的にこの解決策を思いつきました (そして、私はおそらく最初でも最後でもありません!)。ファイルの内容を読む必要があったのは、これが変更を検出するより良い方法だと思われたからです。以下のコードは、まれに TTimer から「CheckForWebNewsOnTimer」を呼び出し、Indy を使用してニュース ページを読み取り、そのコンテンツの MD5 ハッシュを作成して、レジストリに保存されている以前のハッシュと比較します。内容が変わるか、120日が経過すると、ページがポップアップします。コードにはしわがあります。たとえば、ページ上のリンクされた画像を変更しても変更がトリガーされない場合がありますが、ニュースだけで、ほとんどの場合テキストも変更されます。
function StreamToMD5HashHex( AStream : TStream ) : string;
// Creates an MD5 hash hex of this stream
var
idmd5 : TIdHashMessageDigest5;
begin
idmd5 := TIdHashMessageDigest5.Create;
try
result := idmd5.HashStreamAsHex( AStream );
finally
idmd5.Free;
end;
end;
function HTTPToMD5HashHex( const AURL : string ) : string;
var
HTTP : TidHTTP;
ST : TMemoryStream;
begin
HTTP := TidHTTP.Create( nil );
try
ST := TMemoryStream.Create;
try
HTTP.Get( AURL, ST );
Result := StreamToMD5HashHex( ST );
finally
ST.Free;
end;
finally
HTTP.Free;
end;
end;
function ShouldShowNews( const ANewHash : string; AShowAfterDays : integer ) : boolean;
const
Section = 'NewsPrompt';
IDHash = 'LastHash';
IDLastDayNum = 'LastDayNum';
var
sLastHash : string;
iLastPromptDay : integer;
begin
// Check hash
sLastHash := ReadRegKeyUserStr( Section, IDHash, '' );
Result := not SameText( sLastHash, ANewHash );
if not Result then
begin
// Check elapsed days
iLastPromptDay := ReadRegKeyUserInt( Section, IDLastDayNum, 0 );
Result := Round( Now ) - iLastPromptDay > AShowAfterDays;
end;
if Result then
begin
// Save params for checking next time.
WriteRegKeyUserStr( Section, IDHash, ANewHash );
WriteRegKeyUserInt( Section, IDLastDayNum, Round(Now) );
end;
end;
procedure CheckForWebNewsOnTimer;
var
sHashHex, S : string;
begin
try
S := GetNewsURL; // < my news address
sHashHex := HTTPToMD5HashHex( S );
If ShouldShowNews( sHashHex, 120 {days default} ) then
begin
WebBrowserDlg( S );
end;
except
// .. ignore or save as info
end;
end;