Я хочу скачать файл из Интернета, а InternetReadFile на первый взгляд кажется хорошим и простым решением.На самом деле, слишком хорошо, чтобы быть правдой.Действительно, копая немного, я начал понимать, что на самом деле есть много проблем с этим.Люди жалуются на всевозможные проблемы при использовании этого кода.
Могут возникнуть проблемы из-за:
- приложение временно зависает до тех пор, пока HTTP-сервер не ответит
- приложение временно зависает из-за разрыва соединения с Интернетом
- приложение блокируется, потому что HTTP-сервер никогда не отвечает
- InternetOpen (я только что обнаружил это недавно) ДОЛЖЕН вызываться только один раз за время жизни приложения
Я не смог найти полный примеро том, как использовать это правильно и надежно.Кто-нибудь есть идеи о том, как реализовать это в отдельном потоке и с тайм-аутом?Существует еще один простой способ надежно загрузить файл из Интернета.Хотя я не хочу усложнять свою жизнь такими большими библиотеками, как Jedi или даже Indy.
function GetFileHTTP (const fileURL, FileName: String): boolean;
CONST
BufferSize = 1024;
VAR
hSession, hURL: HInternet;
Buffer: array[1..BufferSize] of Byte;
BufferLen: DWORD;
f: File;
sAppName: string;
begin
// result := false;
sAppName := ExtractFileName(Application.ExeName) ;
hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ; { be aware that InternetOpen need only be called once in your application!!!!!!!!!!!!!! }
TRY
hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0) ;
TRY
AssignFile(f, FileName) ;
Rewrite(f, 1) ;
REPEAT
InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
BlockWrite(f, Buffer, BufferLen)
UNTIL BufferLen = 0;
CloseFile(f) ;
Result:= True;
FINALLY
InternetCloseHandle(hURL)
end
FINALLY
InternetCloseHandle(hSession)
END;
END;
Редактировать: Эта функция проверяет, доступно ли подключение к Интернету.Кажется, он работает и на Win98.
{ Are we connected to the Internet? }
function IsConnectedToInternet: Boolean; { Call SHELL32.DLL for Win < Win98 otherwise call URL.dll }
var InetIsOffline: function(dwFlags: DWORD): BOOL; stdcall;
begin
Result:= FALSE;
if IsApiFunctionAvailable('URL.DLL', 'InetIsOffline', @InetIsOffline)
then Result:= NOT InetIsOffLine(0)
else
if IsApiFunctionAvailable('SHELL32.DLL', 'InetIsOffline', @InetIsOffline)
then Result:= NOT InetIsOffLine(0)
end;
Я использую Delphi 7. Большое спасибо.
Редактировать:
Потеря клиентов из-за зависания приложения наПервый запуск - это идеальный рецепт для потери денег.
Писать код, зависящий от платформы Microsoft, плохо.Вы никогда не знаете, установлена ли у клиента версия IE xx.
Установка чего-либо на компьютер пользователя - это все равно что играть с оружием.Это будет иметь неприятные последствия.
(подробнее об этом здесь: http://thesunstroke.blogspot.com/2010/06/programmig-like-there-is-no-ms-windows.html)