0

リモート ファイルがローカル ファイルと同じサイズの場合 (内容が変更されているため、変更時刻が異なっていても)、ダウンロードしようとするとすぐに返されるなど、アプリの HTTP 要求に問題があります。新しいファイルはダウンロードされません。

要するに、私が従っているプロセスは次のとおりです。INTERNET_FLAG_RESYNCHRONIZEフラグを使用して HTTP 接続を設定し、HttpSendRequest() を呼び出します。次に、HTTP ステータス コードを確認すると、「200」であることがわかります。

  • リモート ファイルが更新されても、ローカル コピーと同じサイズのままである場合: アプリの実行後、ローカル ファイルは変更されません。HttpQueryInfo()リクエストを送信した後にwithを呼び出すとHTTP_QUERY_LAST_MODIFIED、サーバーのファイルの実際の最終変更時刻が表示されます。これは、上書きしようとしているローカル ファイルとは異なることがわかります。
  • リモート ファイルが更新され、ファイル サイズがローカル コピーと異なる場合: ダウンロードされ、期待どおりにローカル コピーが上書きされます。

以下は、ヘルパーとエラー チェックを省略したかなり簡略化されたバージョンのコードです。

// szAppName = our app name
HINTERNET hInternetHandle = InternetOpen( szAppName,
    INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
// szServerName = our server name
hInternetHandle = InternetConnect( hInternetHandle, szServerName,
    INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 0 );

// szPath = the file to download
LPCSTR aszDefault[2] = { "*/*", NULL };
DWORD dwFlags = 0
| INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP
| INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS
| INTERNET_FLAG_KEEP_CONNECTION
| INTERNET_FLAG_NO_AUTH
| INTERNET_FLAG_NO_AUTO_REDIRECT
| INTERNET_FLAG_NO_COOKIES
| INTERNET_FLAG_NO_UI
| INTERNET_FLAG_RESYNCHRONIZE;
HINTERNET hHandle = HttpOpenRequest( hInternetHandle, "GET", szPath, NULL,
    NULL, aszDefault, dwFlags, 0 );

DWORD dwTimeOut = 10 * 1000; // In milliseconds
InternetSetOption( hInternetHandle, INTERNET_OPTION_CONNECT_TIMEOUT,
    &dwTimeOut, sizeof( dwTimeOut ) );
InternetSetOption( hInternetHandle, INTERNET_OPTION_RECEIVE_TIMEOUT,
    &dwTimeOut, sizeof( dwTimeOut ) );
InternetSetOption( hInternetHandle, INTERNET_OPTION_SEND_TIMEOUT,
    &dwTimeOut, sizeof( dwTimeOut ) );
DWORD dwRetries = 5;
InternetSetOption( hInternetHandle, INTERNET_OPTION_CONNECT_RETRIES,
    &dwRetries, sizeof( dwRetries ) );

HttpSendRequest( hInternetHandle, NULL, 0, NULL, 0 );

リモート ファイルの最終変更時刻を照会して正確であることがわかったので、実際にサーバーに到達していることがわかります。ファイルが古くなっている場合INTERNET_FLAG_RESYNCHRONIZE、指定するとファイルが強制的に再同期されると思いました。私はそれをすべて間違っていますか?これはまさにそれが機能するはずの方法ですか?


編集: パケット スニファーを使用していくつかの調査を行いました。追加情報を次に示します。

リモート ファイルとローカル ファイルがまったく同じ場合、交換は次のようになります。

GET /test.bmp HTTP/1.1
Accept: */*
If-None-Match: "1c1467112ee6ca1:369"
User-Agent: Internal Testing
Host: ****************
Connection: Keep-Alive

HTTP/1.1 304 Not Modified
Last-Modified: Tue, 27 Apr 2010 17:21:26 GMT
Accept-Ranges: bytes
ETag: "1c1467112ee6ca1:369"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Tue, 27 Apr 2010 18:10:26 GMT

ここで、リモート ファイルが変更されたが、同じファイル サイズのままである場合:

GET /test.bmp HTTP/1.1
Accept: */*
If-None-Match: "1c1467112ee6ca1:369"
User-Agent: Internal Testing
Host: ****************
Connection: Keep-Alive

HTTP/1.1 200 OK
Content-Length: 419958
Content-Type: image/bmp
Last-Modified: Tue, 27 Apr 2010 18:11:17 GMT
Accept-Ranges: bytes
ETag: "b65425835e6ca1:369"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Tue, 27 Apr 2010 18:11:33 GMT
[Block of data]

そのため、サーバーは実際にファイルが変更されたときにファイルを送信していますが、私のアプリはまだ変更されていないように見えます。問題は、アプリが応答を処理する方法にあると考えています。それは私自身のコードではなく、それを書いた人はずっと前に引っ越しました。

私が見つけた 1 つの問題は、上記の両方のシナリオで、 を呼び出すHttpQueryInfo()HTTP_QUERY_STATUS_CODE200 が返されることです。ただし、上記の最初のケースでは、実際のサーバー応答は 200 ではなく 304 であることがわかります。ファイルサイズが同じ場合、ファイルは変更されていません。したがって、私が抱えている問題です!

ですから、私の質問はもっと単純です:HttpQueryInfo()サーバーが 3XX エラーの 1 つを返しているのに、なぜ 200 を返すのでしょうか? オンラインで同様の質問をしている人を見つけましたが、回答がなかったか、Web ブラウザーを直接扱っていました。

4

2 に答える 2

1

HTTPリクエストヘッダーフィールドをINTERNET_FLAG_RESYNCHRONIZE使用しIf-Modified-Sinceてステータスコードをチェックすると思いますが、HTTP_QUERY_LAST_MODIFIEDは(私が思うに)HEADリクエストを実行してHTTPレスポンスLast-Modifiedヘッダーフィールドをチェックします。

試してみてHTTP_QUERY_IF_UNMODIFIED_SINCE、結果を比較HTTP_QUERY_LAST_MODIFIEDHttpQueryInfo()てください [補足として、HTTP スニファーを起動して実行している場合は、私たち全員にとっていくつかの問題が解決される可能性があります...]。

クイック&ダーティなソリューションとして、リクエストするたびにファイルを強制的にリロードするINTERNET_FLAG_RELOAD代わりにを使用できます。INTERNET_FLAG_RESYNCHRONIZE

HTH

于 2010-04-16T19:17:38.780 に答える
1

MSDN によると、INTERNET_FLAG_RESYNCHRONIZE「リソースが最後にダウンロードされてから変更された場合、HTTP リソースをリロードする」だけです。http://msdn.microsoft.com/en-us/library/aa383661(v=vs.85).aspxを参照してください。

によって返される 200HttpQueryInfo()は確かに奇妙です。実際のステータス コードを返す必要があります。

可能であれば、ファイル サイズの比較ではなく、チェックサムの比較を行うようにコードを変更してください。

そうでない場合は、さらにいくつかのことを確認できます。

于 2011-06-20T23:53:14.573 に答える