Domanda

Delphi 6 Prof, Win7 OS.

I have this code to get the file size by URL:

function TDDWIToolObject.GetFileSize(out Size: Int64): boolean;
var
    hInet: HINTERNET;
    hRequest : HINTERNET;
    lpdwBufferLength: DWORD;
    lpdwReserved    : DWORD;
    ServerName: string;
    Resource: string;
    FileSizeBuffer : array[0..32] of char;
    //SizeCard : Cardinal;
begin
    ParseURL(Url, ServerName, Resource);
    Result := False;
    Size := 0;

    hInet := InternetOpen(PChar(_UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
    if hInet=nil then begin
        FErrorCode := GetLastError;
        Exit;
    end;

    try


        hRequest := InternetOpenUrl(hInet, PChar(URL), PCHar(Headers), Length(HEaders), 0, 0);

        try

            FillChar(FileSizeBuffer, SizeOf(FileSizeBuffer), #0);
            lpdwBufferLength := SizeOf(FileSizeBuffer);
            lpdwReserved :=0;

            if not HttpQueryInfo(
                hRequest,
                HTTP_QUERY_CONTENT_LENGTH,
                @FileSizeBuffer, lpdwBufferLength, lpdwReserved) then begin

                FErrorCode:=GetLastError;
                Exit;
            end;

            Size := StrToInt64(StrPas(FileSizeBuffer));
            Result := True;

        finally
            InternetCloseHandle(hRequest);
        end;

    finally
        InternetCloseHandle(hInet);
    end;

end;

It is working good with my machine + DSL connection.

But when I check this code in other place which is fully protected (proxy + many policies) then I get error code 12150... :-(

What is interesting, that I can download this file, when I use this code:

function TDDWIToolObject.DownloadFile;
var
    hInet: HINTERNET;
    hFile: HINTERNET;
    pbuffer: Pointer;
    bytesRead: DWORD;
    Stm : TFileStream;
    TotalBytes : Int64;
    AbortIt : boolean;
begin
    Result := False;
    FErrorCode := -1;
    FAborted := False;
    hInet := InternetOpen(PChar(_UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
    if hInet = nil
        then begin
            FErrorCode := GetLastError;
            Exit;
        end;
    try
        hFile := InternetOpenURL(hInet, PChar(URL), PChar(FHeaders), Length(FHeaders), 0, 0);
        if hFile = nil
            then begin
                FErrorCode := GetLastError;
                Exit;
            end;
        try
            Stm := TFileStream.Create(FN, fmCreate);
            try
                GetMem(pbuffer, FBufferSize);
                try
                    TotalBytes := 0; AbortIt := False;
                    while (not FAborted) do begin
                        if not InternetReadFile(hFile, pbuffer, FBufferSize, bytesRead) then begin
                            FErrorCode := GetLastError;
                            Exit;
                        end;
                        if bytesRead > 0 then begin
                            Stm.WriteBuffer(pbuffer^, bytesRead);
                            if Assigned(FOnBytesArrived)
                                then begin
                                    inc(TotalBytes, bytesRead);
                                    FOnBytesArrived(Self, TotalBytes, AbortIt);
                                    if AbortIt
                                        then Abort;
                                end;
                        end else begin
                            break;
                        end;
                    end;
                finally
                    FreeMem(pbuffer);
                end;
                if not FAborted
                    then Result := True;
            finally
                Stm.Free;
            end;
        finally
            InternetCloseHandle(hFile);
        end;
    finally
        InternetCloseHandle(hInet);
    end;
end;

It is interesting because sysadmin allowed the requests to this URL in proxy, and the downloads work for me - only the content length requests fail.

I want to ask one question, but it is hard to do, because many of them is in my mind... Do you have some idea what we can do to allow the requests? Maybe HttpRequest uses another port, or some "illegal" what isn't proxiable? Or my code is seems to be wrong? Why it is working in nonprotected area? What are the differents between download and get content length requests?

So the question is as in summarized format: do you have some idea what can I do to I get the file size before downloading?

Thanks for it.

È stato utile?

Soluzione

This error can be caused by many factors (ERROR_HTTP_HEADER_NOT_FOUND), in your code you are not checking the result of the InternetOpenUrl function before to call the HttpQueryInfo method, and I don't see the content of the _UserAgent and Headers variables to give you a more exact answer. Anyway try using the HttpOpenRequest and HttpSendRequest functions instead of InternetOpenURL.

Try this sample

uses
  Windows,
  SysUtils,
  WinInet;


const
  sUserAgent = 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101';

function GetWinInetError(ErrorCode:Cardinal): string;
const
   winetdll = 'wininet.dll';
var
  Len: Integer;
  Buffer: PChar;
begin
  Len := FormatMessage(
  FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM or
  FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_IGNORE_INSERTS or  FORMAT_MESSAGE_ARGUMENT_ARRAY,
  Pointer(GetModuleHandle(winetdll)), ErrorCode, 0, @Buffer, SizeOf(Buffer), nil);
  try
    while (Len > 0) and {$IFDEF UNICODE}(CharInSet(Buffer[Len - 1], [#0..#32, '.'])) {$ELSE}(Buffer[Len - 1] in [#0..#32, '.']) {$ENDIF} do Dec(Len);
    SetString(Result, Buffer, Len);
  finally
    LocalFree(HLOCAL(Buffer));
  end;
end;


procedure ParseURL(const lpszUrl: string; var Host, Resource: string);
var
  lpszScheme      : array[0..INTERNET_MAX_SCHEME_LENGTH - 1] of Char;
  lpszHostName    : array[0..INTERNET_MAX_HOST_NAME_LENGTH - 1] of Char;
  lpszUserName    : array[0..INTERNET_MAX_USER_NAME_LENGTH - 1] of Char;
  lpszPassword    : array[0..INTERNET_MAX_PASSWORD_LENGTH - 1] of Char;
  lpszUrlPath     : array[0..INTERNET_MAX_PATH_LENGTH - 1] of Char;
  lpszExtraInfo   : array[0..1024 - 1] of Char;
  lpUrlComponents : TURLComponents;
begin
  ZeroMemory(@lpszScheme, SizeOf(lpszScheme));
  ZeroMemory(@lpszHostName, SizeOf(lpszHostName));
  ZeroMemory(@lpszUserName, SizeOf(lpszUserName));
  ZeroMemory(@lpszPassword, SizeOf(lpszPassword));
  ZeroMemory(@lpszUrlPath, SizeOf(lpszUrlPath));
  ZeroMemory(@lpszExtraInfo, SizeOf(lpszExtraInfo));
  ZeroMemory(@lpUrlComponents, SizeOf(TURLComponents));

  lpUrlComponents.dwStructSize      := SizeOf(TURLComponents);
  lpUrlComponents.lpszScheme        := lpszScheme;
  lpUrlComponents.dwSchemeLength    := SizeOf(lpszScheme);
  lpUrlComponents.lpszHostName      := lpszHostName;
  lpUrlComponents.dwHostNameLength  := SizeOf(lpszHostName);
  lpUrlComponents.lpszUserName      := lpszUserName;
  lpUrlComponents.dwUserNameLength  := SizeOf(lpszUserName);
  lpUrlComponents.lpszPassword      := lpszPassword;
  lpUrlComponents.dwPasswordLength  := SizeOf(lpszPassword);
  lpUrlComponents.lpszUrlPath       := lpszUrlPath;
  lpUrlComponents.dwUrlPathLength   := SizeOf(lpszUrlPath);
  lpUrlComponents.lpszExtraInfo     := lpszExtraInfo;
  lpUrlComponents.dwExtraInfoLength := SizeOf(lpszExtraInfo);

  InternetCrackUrl(PChar(lpszUrl), Length(lpszUrl), ICU_DECODE or ICU_ESCAPE, lpUrlComponents);

  Host := lpszHostName;
  Resource := lpszUrlPath;
end;

function GetRemoteFileSize(const Url : string): Integer;
var
  hInet    : HINTERNET;
  hConnect : HINTERNET;
  hRequest : HINTERNET;
  lpdwBufferLength: DWORD;
  lpdwReserved    : DWORD;
  ServerName: string;
  Resource: string;
  ErrorCode : Cardinal;
begin
  ParseURL(Url,ServerName,Resource);
  Result:=0;

  hInet := InternetOpen(PChar(sUserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if hInet=nil then
  begin
    ErrorCode:=GetLastError;
    raise Exception.Create(Format('InternetOpen Error %d Description %s',[ErrorCode,GetWinInetError(ErrorCode)]));
  end;

  try
    hConnect := InternetConnect(hInet, PChar(ServerName), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
    if hConnect=nil then
    begin
      ErrorCode:=GetLastError;
      raise Exception.Create(Format('InternetConnect Error %d Description %s',[ErrorCode,GetWinInetError(ErrorCode)]));
    end;

    try
      hRequest := HttpOpenRequest(hConnect, PChar('HEAD'), PChar(Resource), nil, nil, nil, 0, 0);
        if hRequest<>nil then
        begin
          try
            lpdwBufferLength:=SizeOf(Result);
            lpdwReserved    :=0;
            if not HttpSendRequest(hRequest, nil, 0, nil, 0) then
            begin
              ErrorCode:=GetLastError;
              raise Exception.Create(Format('HttpOpenRequest Error %d Description %s',[ErrorCode,GetWinInetError(ErrorCode)]));
            end;

             if not HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER, @Result, lpdwBufferLength, lpdwReserved) then
             begin
              Result:=0;
              ErrorCode:=GetLastError;
              raise Exception.Create(Format('HttpQueryInfo Error %d Description %s',[ErrorCode,GetWinInetError(ErrorCode)]));
             end;
          finally
            InternetCloseHandle(hRequest);
          end;
        end
        else
        begin
          ErrorCode:=GetLastError;
          raise Exception.Create(Format('HttpOpenRequest Error %d Description %s',[ErrorCode,GetWinInetError(ErrorCode)]));
        end;
    finally
      InternetCloseHandle(hConnect);
    end;
  finally
    InternetCloseHandle(hInet);
  end;

end;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top