Maks150988
Advanced Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Это, вобщем возник такой вопрос. Я должен скачать файл с сервера. Необходимо перед закачкой данных проверить наличие файла на сервере и номер ошибки. Если 200 - качаем. Ранее использовал функции WinInet и код был таким, в коде вроде все должно работать как часы, наверное: Код: function GetTextFileFromServer(szURL : AnsiString) : AnsiString; var FSession : HINTERNET; hConnect : HINTERNET; szBuffer : Array [0..4095] of AnsiChar; dwIndex : DWORD; dwCodeLen : DWORD; hRequest : LongBool; szNotify : AnsiString; dwTimeout : Integer; dwRead : Cardinal; begin Result := ''; try { открываем интернет сессию для выполнения последующих действий } FSession := InternetOpen('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); { устанавливаем таймер на сессию - 10 секунд } dwTimeout := 10 * 1000; InternetSetOption(FSession, INTERNET_OPTION_CONNECT_TIMEOUT, @dwTimeout, SizeOf(dwTimeout)); InternetSetOption(FSession, INTERNET_OPTION_RECEIVE_TIMEOUT, @dwTimeout, SizeOf(dwTimeout)); InternetSetOption(FSession, INTERNET_OPTION_SEND_TIMEOUT, @dwTimeout, SizeOf(dwTimeout)); if FSession <> nil then try { получаем хэндл открытого файла по сети } hConnect := InternetOpenUrl(FSession, PAnsiChar(szURL), nil, 0, INTERNET_FLAG_NO_UI, 0); if hConnect <> nil then try { проверяем открытое соединение на ошибки } dwIndex := 0; dwCodeLen := Length(szBuffer); hRequest := HttpQueryInfo(hConnect, HTTP_QUERY_STATUS_CODE, @szBuffer[0], dwCodeLen, dwIndex); if hRequest then begin szNotify := szBuffer; { если код ошибки 200 - все прошло нормально и продолжаем } if szNotify = '200' then begin repeat FillChar(szBuffer, SizeOf(szBuffer), 0); if InternetReadFile(hConnect, @szBuffer[0], SizeOf(szBuffer), dwRead) then Result := Result + szBuffer else Break; until dwRead = 0; end; end; finally InternetCloseHandle(hConnect); end; finally InternetCloseHandle(FSession); end; except end; end; | А наверное потому, потому как непонятно, почему вслучае неудачного соединения файл перестает закачиваться (функция возвращает пустой результат) и помогает только перезапуск программы. Собственно решил перейти на сокеты. Почитал что пишут на форумах и за основу взял код и переделал под свои нужды. Конечно понравилось что все так быстро через сокеты грузит, но, хотелось бы сделать аналог HttpQueryInfo для проверки 200 кода. А также такой вопрос, помимо ответа с сервера возвращаются и другие данные - тип контента, его длина, время и т.д. Все это вначале возвращаемых данных. Я так понимаю это что-то типа приходящего пакета? Якобы заголовок или подобие? Или я ошибаюсь. Как можно извлечь то, что реально требуется, как в этом случае возвратило бы через WinInet функции? Парсить вручную чтоли? Вот код: Код: function GetHttpData(szURL, szMethod : AnsiString; TargetPort : WORD; szArgs, szContnt : AnsiString) : AnsiString; const szUserAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; CRLF = #13#10; var hSocket : TSocket; SockAddr : TSockAddr; szBuffer : Array [0..1023] of AnsiChar; BuffSize : Cardinal; WSAData : TWSAData; szTemp : AnsiString; szHost : AnsiString; begin { возвращаем пустой результат в функцию } Result := ''; { извлекаем название хоста для соединения } szTemp := szURL; if Pos('//', szTemp) > 0 then Delete(szTemp, 1, Pos('//', szTemp) + 1); szHost := Copy(szTemp, 1, Pos('/', szTemp) - 1); { запускаем библиотеку winsock версии 2 } WSAStartup(MAKEWORD(2, 0), WSAData); { создаем сокет с нужными нам параметрами } hSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); SockAddr.sin_family := AF_INET; SockAddr.sin_addr := PInAddr(GetHostByName(PAnsiChar(szHost))^.h_addr_list^)^; SockAddr.sin_port := htons(TargetPort); { если не удалось соединиться - останавливаемся } if connect(hSocket, SockAddr, SizeOf(SockAddr)) = SOCKET_ERROR then begin closesocket(hSocket); Exit; end; { формируем строку для отправки запроса } szTemp := Format('%s %s HTTP/1.1'+ CRLF + '%s' + CRLF + 'User-Agent: %s' + CRLF + 'Host: %s' + CRLF + 'Content-Length: %s' + CRLF + 'Connection: Keep-Alive' + CRLF + 'Cache-Control: no-cache' + CRLF + CRLF + szArgs, [szMethod, szURL, szContnt, szUserAgent, szHost, IntToStr(Length(szArgs))]); { отправляем через сокет запрос } if send(hSocket, Pointer(szTemp)^, Length(szTemp), 0) = SOCKET_ERROR then begin closesocket(hSocket); Exit; end; { получаем результат и сохраняем его } FillChar(szBuffer, SizeOf(szBuffer), 0); repeat BuffSize := recv(hSocket, szBuffer, SizeOf(szBuffer), 0); if BuffSize > 0 then begin Result := Result + PAnsiChar(@szBuffer); FillChar(szBuffer, SizeOf(szBuffer), 0); end; until BuffSize > 0; { очищаем буфер, закрываем сокет и выгружаем winsock } FillChar(szBuffer, SizeOf(szBuffer), 0); closesocket(hSocket); WSACleanup; end; //s:=GetHttpData('http://адрес.ru/file.rar', 'GET', 80, '', 'Content-Type: text/plain'); |
|