У меня проблема с моими HTTP-запросами в моем приложении, так что, если удаленный файл имеет тот же размер, что и локальный файл (даже если время его изменения отличается, так как его содержимое было изменено), попытка загрузки он быстро возвращается и новый файл не загружается.
Короче говоря, процесс, которым я следую, заключается в следующем: настройка HTTP-соединения с флагом INTERNET_FLAG_RESYNCHRONIZE
и вызов HttpSendRequest (); затем проверяет код состояния HTTP и находит его равным «200».
- Если удаленный файл обновляется, но остается того же размера, что и локальная копия : Локальный файл не изменяется после запуска приложения. Если после отправки запроса я позвоню
HttpQueryInfo()
с 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]
Итак, сервер действительно отправляет файл, когда он изменился, но мое приложение все еще видит его как не изменившийся. Я думаю, что проблема заключается в том, как мое приложение справляется с ответом; это не мой собственный код, и парень, который его написал, давно ушел.
Одна проблема, которую я обнаружил, заключается в том, что в обоих из вышеупомянутых сценариев, когда я звоню HttpQueryInfo()
с HTTP_QUERY_STATUS_CODE
, я получаю 200 обратно. Тем не менее, в первом случае, приведенном выше, я вижу, что фактический ответ сервера был 304, а не 200. Изучив код, который мы используем, я обнаружил, что он пытается обойти эту проблему, сравнивая размер файла и предполагая, что файл не изменился, если размеры файлов совпадают; следовательно, проблема, с которой я столкнулся!
Так что теперь мой вопрос более прост: почему HttpQueryInfo()
возвращает 200, даже если сервер возвращает одну из ошибок 3XX? Я обнаружил, что некоторые люди задают аналогичный вопрос в Интернете, но они либо не получили ответов , либо имели дело с веб-браузерами напрямую.