Столкнулся с проблемой на Delphi-XE5. Ни одна из 3 работавших в более ранних версиях функция не хочет сообщить мне размер скачиваемого мной файла (нужно для индикации прогрессбаром). 2 функции на модуле wininet и один способ на THDHTP компоненте. Вопрос к уважаемым форумчанам как средствами Делфи ХЕ5 это реализовать? Рыл интернет всю ночь....
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
08-07-2015 01:36
Перешел на индейцев полностью. Все работает. WININET забыл и не использую больше.
Это работает:
function GetInetFileSize(const FileUrl:string): integer;
var
idHTTP: TidHTTP;
begin
Result:=0;
idHTTP:=TIdHTTP.Create(nil);
idHTTP.Head(FileUrl);
Result:=idHTTP.Response.ContentLength;
IdHTTP.Free;
end;
дальше можно использовать так:
ProgressBar1.Max:=GetInetFileSize(URL);
To Python: у меня катастрофически мало времени. Сплю 4 часа... Попробовать могу любой проект, но готовый. Слепите все в одно целое, я сразу сообщу результат.
To Oleg_Guz:
Спасибо за тестирование. Я вот не собираюсь с семёрки (Delphi я имею в виду, а не винду) никуда уходить, так что судить о том, что произойдёт на более новых версиях не могу. Сделал кое-какие изменения, в данном случае просто проблемную 411 строчку удалил (она преобразует кодировку в OEM, функция взята из другого, более универсального модуля и здесь не используется). Должно получиться что-то такое:
if I<=0 then Result:=inttostr(ErrorCode)
else begin
P[I+1]:=#0;
{if Oem then CharToOem(P,P);}
Result:=P;
end;
При необходимости, можно также убрать из заголовка Oem:boolean=false, но это в качестве временной меры не обязательно. Для исправления варнингов требуется строки 277,278 исправить так:
Здесь я просто закомментировал объявление длины строки, чтобы понятно было, что удалить надо.
Насчёт варнинга из 407 строки - не вижу никакой ошибки. Если найдёте метод убирания этого варнинга, прошу сообщить (желательно - в обсуждении компонента), чтобы я мог включить это исправление в новую версию компонента.
Ну а варнинг в 215 строке совсем непонятен. В VCL приложении и так M+ включена. В принципе, можно воткнуть эту директиву явно в начало модуля, но необходимости делать этого я не вижу. В связи с тем, что я собираюсь отказаться от возможности использования THTTPGet как компонента, я думаю, что published будет заменено на public и всё будет хорошо.
[dcc32 Error] HttpGet.pas(411): E2010 Incompatible types: 'PAnsiChar' and 'PWideChar'
[dcc32 Warning] HttpGet.pas(215): W1055 PUBLISHED caused RTTI ($M+) to be added to type 'THTTPGet'
[dcc32 Warning] HttpGet.pas(294): W1057 Implicit string cast from 'ShortString' to 'string'
[dcc32 Warning] HttpGet.pas(296): W1057 Implicit string cast from 'ShortString' to 'string'
[dcc32 Warning] HttpGet.pas(322): W1057 Implicit string cast from 'ShortString' to 'string'
[dcc32 Warning] HttpGet.pas(326): W1057 Implicit string cast from 'ShortString' to 'string'
[dcc32 Warning] HttpGet.pas(407): W1050 WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in 'SysUtils' unit.
и еще столько же...
То, что в прежних версиях компилировалось в ХЕ5 выдает несовместимость типов.
Дважды запрашивать сервер только для того, чтобы определить размер - это точно не гуд. На правах рекламы: попробуйте воспользоваться моим решением - там отдельный поток, отдельное событие OnProgress, а в новой версии прогресс можно будет получать и через таймер (скоро будет выложена).
function GetUrlSize(const URL:string):Integer;
var
hSession,hFile:hInternet;
dwBuffer:array[1..20] of Char;
dwBufferLen,dwIndex:DWORD;
begin
Result:=0;
hSession:=InternetOpen('GetUrlSize',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
if Assigned(hSession) then begin
hFile:=InternetOpenURL(hSession,PChar(URL),nil,0,
INTERNET_FLAG_RELOAD,0);
dwIndex:=0;dwBufferLen:=20;
if HttpQueryInfo(hFile,HTTP_QUERY_CONTENT_LENGTH,
@dwBuffer,dwBufferLen,dwIndex)
then Result:=StrToInt(dwBuffer);
if Assigned(hFile) then InternetCloseHandle(hFile);
InternetCloseHandle(hsession);
end;
end;
Void -у меня уже крыша едет. Вставил я предложенную Вами функцию. http://www.cryer.co.uk/brian/delphi/wininet/example_isurlvalid.htm
передал ей урл скачеваемого файла
Пробую передавать значения на form1.Caption:=IntTostr(bufLen); для наглядности
Не могу понять, как получить размер?
В одном 1 случае мне на форму вывело 501 (файл более з-ех мгбайт)во 2 месте 6
begin
//———————————————
// Create a request for the url.
//———————————————
dummy := 0;
bufLen := Length(infoBuffer);
//1 form1.Caption:=IntTostr(bufLen);
okay := HttpQueryInfo(hConnect,HTTP_QUERY_STATUS_CODE,
@infoBuffer[0],bufLen,dummy);
if not okay then
// Probably working offline, or no internet connection.
result := False
else
begin
reply := infoBuffer;
if reply = '200' then begin
// File exists, all ok.
//2 form1.Caption:=IntTostr(bufLen);
result := True
end
Уже мозг поплыл
Почему параметр dwBuffer у Вас передается как @dwBuffer ?
Вроде как это должен быть заранее выделенный массив, а не указатель типа Pointer, и передавать нужно будет как @dwBuffer[0]. Причем в lpdwBufferLength передается длина этого массива.
Тут гляньте пример: http://www.cryer.co.uk/brian/delphi/wininet/example_isurlvalid.htm
Задаю ProgressBar1.Max:=3144560; вручную и все работает. Раньше получал через функцию.
procedure TForm1.Image3Click(Sender: TObject);
var
FileOnNet, LocalFileName: string;
begin
try
FileOnNet := 'http://www.мой сайт файл.rar';
LocalFileName := 'TEMP\файл.rar';
ProgressBar1.Max:=3144560;
if GetInetFile(FileOnNet, LocalFileName) = True then Begin
with CreateInArchive(CLSID_CFormatRar) do
begin
OpenFile(ExtractFilePath(ParamStr(0)) + 'TEMP\telemaster.rar');
ExtractTo(INI.ReadString('MODS','patch','C:\telemaster'));
showmessage('Закачано');
end;
ShowMessage('Установка завершена успешно!');
end else ShowMessage('Отсутствует связь с сервером');
finally
end;
end;
А еще раньше можно было просто получить размер файла
uses IdHTTP
procedure TForm1.Image1Click(Sender: TObject);
begin
Вот это одна не возвращает, а тупо выдает ошибку времени выполнения
function TForm1.GetUrlInfo(const dwInfoLevel: DWORD; const FileURL: string): string;
var
hSession, hFile: hInternet;
dwBuffer: Pointer;
dwBufferLen, dwIndex: DWORD;
begin
Result := '';
hSession := InternetOpen('STEROID Download', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(hSession) then begin
hFile := InternetOpenURL(hSession, PChar(FileURL), nil, 0, INTERNET_FLAG_RELOAD, 0);
dwIndex := 0;
dwBufferLen := 20;
if HttpQueryInfo(hFile, dwInfoLevel, @dwBuffer, dwBufferLen, dwIndex)
then Result := PChar(@dwBuffer);
if Assigned(hFile) then InternetCloseHandle(hFile);
InternetCloseHandle(hsession);
end;
end;
а вот другая
function GetUrlSize(dwInfoLevel: DWORD; FileURL: string):string;
var
hSession, hFile: hInternet;
dwBuffer: Pointer;
dwBufferLen, dwIndex: DWORD;
begin
Result := '';
hSession := InternetOpen('STEROID Download',
INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(hSession) then begin
hFile := InternetOpenURL(hSession, PChar(FileURL), nil, 0,
INTERNET_FLAG_RELOAD, 0);
dwIndex := 0;
dwBufferLen := 20;
if HttpQueryInfo(hFile, dwInfoLevel, @dwBuffer, dwBufferLen, dwIndex)
then Result := PChar(@dwBuffer);
if Assigned(hFile) then InternetCloseHandle(hFile);
InternetCloseHandle(hsession);
end;
end;
компилятор не принимает эту строку if HttpQueryInfo(hFile, dwInfoLevel, @dwBuffer, dwBufferLen, dwIndex)пишет не совместимые типы dwInfoLevel, @dwBuffer, dwBufferLen,
а третий способ через компонент плохо скачивает, размер тоже не дает и я его не смотрю
01-06-2014 08:12 | Вопрос к автору: запрос дополнительной информации
По-моему, способ ровно один: заголовок Content-Length в ответе сервера. Разумеется, если скачиваете по HTTP. Если отправить на сервер запрос HEAD, сервер может (но не обязан) вернуть размер файла в заголовке Content-Length. С помощью какой библиотеки этот запрос отправлять — дело десятое.
>>>Ни одна из 3 работавших в более ранних версиях функция не хочет сообщить мне размер скачиваемого мной файла
Что за функции?
Более ранние версии Delphi — это какие?
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.