6

次の機能を実装したいと思います。

  1. AC#クライアントはHTTPサーバーに接続し、イメージをディスクにダウンロードします。

  2. 次回クライアントが起動すると、サーバー上のイメージがディスク上のイメージよりも新しいかどうかがチェックされます。この場合、クライアントはディスク上のイメージを上書きします。

私にとってはイメージをダウンロードするのは簡単ですが、サーバー上のイメージが新しいかどうかを確認する方法がわかりません。どうすれば実装できますか?タイムスタンプまたは画像サイズ(あるいはその両方)を確認できたと思いますが、その方法がわかりません。

4

3 に答える 3

6

If-Modified-Sinceリクエストフィールドをお試しください。http://en.wikipedia.org/wiki/List_of_HTTP_header_fields すべてのサーバーで完全にサポートされているかどうかはわかりません。したがって、サポートされていなくてもファイルを取得できる場合 (サポートされている場合は 304 ではない)、チェックサムを計算し、それらが異なる場合はファイルが変更されたと見なすことができます。または上書きするだけで、常に最新バージョンになります。

于 2012-08-07T16:40:43.280 に答える
5

HttpWebRequest は IE キャッシュを使用するだけなので、とにかくすべての画像がそのキャッシュにあり、ファイルを書き換えるコスト (ダウンロードする必要はない) が許容できる場合は、それを利用することができます。

ただし、自分で処理する必要がある場合は、次のようにします。

与えられた:

string uri; //URI of the image.
DateTime? lastMod; // lastModification date of image previously recorded. Null if not known yet.
string eTag; //eTag of image previously recorded. Null if not known yet.

これの最後にこれらを保存し、最初に (新しい画像ではない場合) 再度取得する必要があります。それはあなた次第です、それを考えると、残りはうまくいきます:

var req = (HttpWebRequest)WebRequest.Create(uri);
if(lastMod.HasValue)
  req.IfModifiedSince = lastMod.Value;//note: must be UTC, use lastMod.Value.ToUniversalTime() if you store it somewhere that converts to localtime, like SQLServer does.
if(eTag != null)
  req.AddHeader("If-None-Match", eTag);
try
{
  using(var rsp = (HttpWebResponse)req.GetResponse())
  {
    lastMod = rsp.LastModified;
    if(lastMod.Year == 1)//wasn't sent. We're just going to have to download the whole thing next time to be sure.
      lastMod = null;
    eTag = rsp.GetResponseHeader("ETag");//will be null if absent.
    using(var stm = rsp.GetResponseStream())
    {
      //your code to save the stream here.
    }
  }
}
catch(WebException we)
{
  var hrsp = we.Response as HttpWebResponse;
  if(hrsp != null && hrsp.StatusCode == HttpStatusCode.NotModified)
  {
    //unfortunately, 304 when dealt with directly (rather than letting
    //the IE cache be used automatically), is treated as an error. Which is a bit of
    //a nuisance, but manageable. Note that if we weren't doing this manually,
    //304s would be disguised to look like 200s to our code.

    //update these, because possibly only one of them was the same.
    lastMod = hrsp.LastModified;
    if(lastMod.Year == 1)//wasn't sent.
      lastMod = null;
    eTag = hrsp.GetResponseHeader("ETag");//will be null if absent.
  }
  else //some other exception happened!
    throw; //or other handling of your choosing
}

E タグは、正しく実装されている場合、最終変更よりも信頼性が高くなります (変更が 1 秒未満で解決され、異なる Accept-* ヘッダーによる異なる応答が反映されることに注意してください)。ただし、一部の実装にはバグがあります (Web ファーム上の IIS6、特定の微調整なしの Apache、mod-gzip を使用した Apache)。

編集: HTTP キャッシュの実装をさらに進めたい場合は、expires と max-age (両方が存在し、前者と一致しない場合は後者を使用) を保存し、それらよりも早い場合はダウンロードを完全にスキップすることもできます。値が示唆します。私はこれを実行しましたが、うまく機能します (さまざまな URI によって返された XML から作成されたオブジェクトのメモリ内キャッシュがあり、XML が新しいか変更されていない場合は、オブジェクトを再利用しました)。あなたのニーズには関係ないかもしれません (サーバーが提案するよりも新鮮であることを気にしている場合、または常にそのウィンドウの外にいる場合)。

于 2012-08-07T17:06:16.827 に答える