Почему URLDownloadToFile::OnProgress всегда возвращает ulProgress и ulProgressMax с одинаковым значением

#delphi #download

#delphi #Скачать

Вопрос:

Это мой код delphi:

 TDownloadCallback = class(TInterfacedObject, IBindStatusCallback)
private
    fOwner: TDownload;
    fUrl: string;
public
    constructor Create(owner: TDownload; url: string);

    function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResu< stdcall;
    function GetPriority(out nPriority): HResu< stdcall;
    function OnLowResource(reserved: DWORD): HResu< stdcall;
    function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG; szStatusText: LPCWSTR): HResu< stdcall;
    function OnStopBinding(hresult: HResu< szError: LPCWSTR): HResu< stdcall;
    function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResu< stdcall;
    function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc: PFormatEtc; stgmed: PStgMedium): HResu< stdcall;
    function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResu< stdcall;
end;

TDownloadStatus =
(
dsNULL                , dsFindingresource         , dsConnecting              , dsRedirecting,
dsBegindownloaddata   , dsDownloadingdata         , dsEnddownloaddata         , dsBegindownloadcomponents,
dsInstallingcomponents, dsEnddownloadcomponents   , dsUsingcachedcopy         , dsSendingrequest,
dsClassidavailable    , dsMimetypeavailable       , dsCachefilenameavailable  , dsBeginsyncoperation,
dsEndsyncoperation    , dsBeginuploaddata         , dsUploadingdata           , dsEnduploadingdata,
dsProtocolclassid     , dsEncoding                , dsVerfiedmimetypeavailable, dsClassinstalllocation,
dsDecoding            , dsLoadingmimehandler      , dsContentdispositionattach, dsFilterreportmimetype,
dsClsidcaninstantiate , dsIunknownavailable       , dsDirectbind              , dsRawmimetype,
dsProxydetecting      , dsAcceptranges
);

const
  WinNetLib = 'Wininet.DLL';

function DeleteUrlCacheEntry(pszUrl: PChar): BOOL; stdcall; external WinNetLib name 'DeleteUrlCacheEntry';

{ TDownloadCallback }

constructor TDownloadCallback.Create(owner: TDownload; url: string);
begin
  fOwner := owner;
  fUrl := url;
end;

function TDownloadCallback.GetBindInfo(out grfBINDF: DWORD;
  var bindinfo: TBindInfo): HResu<
begin
  DeleteUrlCacheEntry(PChar(fUrl));
  Result := S_OK;
end;

function TDownloadCallback.GetPriority(out nPriority): HResu<
begin
  Result := S_OK;
end;

function TDownloadCallback.OnDataAvailable(grfBSCF, dwSize: DWORD;
  formatetc: PFormatEtc; stgmed: PStgMedium): HResu<
begin
  Result := S_OK;
end;

function TDownloadCallback.OnLowResource(reserved: DWORD): HResu<
begin
  Result := S_OK;
end;

function TDownloadCallback.OnObjectAvailable(const iid: TGUID;
  punk: IInterface): HResu<
begin
  Result := S_OK;
end;

function TDownloadCallback.OnProgress(ulProgress, ulProgressMax,
  ulStatusCode: ULONG; szStatusText: LPCWSTR): HResu<
var
  status: TDownloadStatus;
begin
  if fOwner.fProgress <> nil then
  begin
    status := TDownloadStatus(ulStatusCode);
    case (status) of
    dsBegindownloaddata:
      begin
        fOwner.fProgress.Max := ulProgressMax;
        DeleteUrlCacheEntry(PChar(szStatusText));
      end;
    dsDownloadingdata:
      begin
        // progressbar here!
      end;
    end;
  end;

  Form1.Memo1.Lines.Add(Format('ulProgress: %d, ulProgressMax: %d, ulStatusCode: %d (%s), szStatusText: %s', [
    ulProgress, ulProgressMax, ulStatusCode, GetEnumName(TypeInfo(TDownloadStatus), Integer(status)), szStatusText
  ]));

  Result := S_OK;
  Application.ProcessMessages;
end;

function TDownloadCallback.OnStartBinding(dwReserved: DWORD;
  pib: IBinding): HResu<
begin
  Result := S_OK;
end;

function TDownloadCallback.OnStopBinding(hresult: HResu<
  szError: LPCWSTR): HResu<
begin
  Result := S_OK;
end;

procedure download(url, filename: string);
var
  intf: IBindStatusCallback;
begin
  CoInitialize(nil);
  try
    intf := TDownloadCallback.Create(self, url);
    try
      URLDownloadToFile(nil, PChar(url), Pchar(filename), 0, intf);
    finally
      intf := nil;
    end;
  finally
    CoUninitialize;
  end;
end;
 

Когда я вызываю download('htp://....', 'filename.exe') свою заметку, печатается:

 ulProgress: 0, ulProgressMax: 0, ulStatusCode: 32 (dsProxydetecting), szStatusText: 
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 1 (dsFindingresource), szStatusText: www.jjw.com.br
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 2 (dsConnecting), szStatusText: 177.200.200.199
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 11 (dsSendingrequest), szStatusText: 
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 64 (@
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 3 (dsRedirecting), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 32 (dsProxydetecting), szStatusText: 
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 1 (dsFindingresource), szStatusText: get.anydesk.com
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 2 (dsConnecting), szStatusText: 188.40.104.135
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 11 (dsSendingrequest), szStatusText: 
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 26 (dsContentdispositionattach), szStatusText: C:UsersJJWAppDataLocalMicrosoftWindowsTemporary Internet FilesContent.IE5YQIDXOIQjjwsuporteremotoFAYWSU4M.exe
ulProgress: 0, ulProgressMax: 0, ulStatusCode: 13 (dsMimetypeavailable), szStatusText: application/x-msdownload
ulProgress: 32398, ulProgressMax: 32398, ulStatusCode: 4 (dsBegindownloaddata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 32398, ulProgressMax: 32398, ulStatusCode: 14 (dsCachefilenameavailable), szStatusText: C:UsersJJWAppDataLocalMicrosoftWindowsTemporary Internet FilesContent.IE5YQIDXOIQjjwsuporteremotoFAYWSU4M.exe
ulProgress: 48774, ulProgressMax: 48774, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 65158, ulProgressMax: 65158, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 81534, ulProgressMax: 81534, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 97918, ulProgressMax: 97918, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 114294, ulProgressMax: 114294, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 130678, ulProgressMax: 130678, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 147054, ulProgressMax: 147054, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 163438, ulProgressMax: 163438, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 179814, ulProgressMax: 179814, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 196198, ulProgressMax: 196198, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 212574, ulProgressMax: 212574, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 278094, ulProgressMax: 278094, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 294478, ulProgressMax: 294478, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 327238, ulProgressMax: 327238, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 343614, ulProgressMax: 343614, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 392758, ulProgressMax: 392758, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 474654, ulProgressMax: 474654, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 540174, ulProgressMax: 540174, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 572934, ulProgressMax: 572934, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 589318, ulProgressMax: 589318, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1326414, ulProgressMax: 1326414, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1342798, ulProgressMax: 1342798, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1424694, ulProgressMax: 1424694, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1441078, ulProgressMax: 1441078, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1473838, ulProgressMax: 1473838, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1490214, ulProgressMax: 1490214, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 1703158, ulProgressMax: 1703158, ulStatusCode: 5 (dsDownloadingdata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
ulProgress: 2127952, ulProgressMax: 2127952, ulStatusCode: 6 (dsEnddownloaddata), szStatusText: https://get.anydesk.com/psTS1FIS/jjwsuporteremoto.exe
 

Обратите внимание, что ulProgress и ulPorgressMax всегда возвращают одно и то же значение, и оно меняется.

Как я могу создать реальную progressbar на основе размера файла (заголовок Content-Length), используя UrlDownloadToFile ?

Комментарии:

1. Некоторые веб-серверы не предоставляют заголовок content length, поэтому лучшее предположение о размере файла — это то, сколько вы уже получили.

2. @Brian спасибо за трюк, это была моя ошибка. Вы можете ответить на вопрос этим комментарием, и я приму его.

3. Обратите внимание, что это даже указано в OnProgress документации : » ulProgressMax [in] Длинное целое число без знака, которое содержит ожидаемое максимальное значение параметра ulProgress для продолжительности вызовов IBindStatusCallback::OnProgress для этой операции привязки. Обратите внимание, что это значение может меняться при вызовах этого метода. Нулевое значение означает, что максимальное значение ulProgress неизвестно ; например, в методе IMoniker::BindToStorage, когда размер загружаемых данных неизвестен. »

4. @RemyLebeau единственный случай здесь заключается в том, что api не отправляет НОЛЬ, он всегда отправляет «загруженный размер».

5. @BetoNeto тем не менее, это подпадает под документально подтвержденное предложение «это значение может изменяться при вызовах этого метода».

Ответ №1:

Некоторые веб-серверы не предоставляют заголовок content length, поэтому лучшее предположение о размере файла — это то, сколько было получено на данный момент.

Комментарии:

1. Ресурс / загрузка может быть создана «на лету» (т. Е. TAR или ZIP) и предлагается как таковой сразу, вместо того, чтобы ждать, пока он не будет готов полностью — аналогично, общий размер файла может быть даже неизвестен серверу.