Pergunta

Eu tenho a seguinte tarefa: baixar um arquivo usando HTTPS e autenticação. Indy parece ser o caminho a percorrer, mas por algum motivo ele não funciona tão longe. Eu tenho o seguinte no lugar:

  • um componente TIdHTTP que eu uso para fazer o download
  • um componente TIdURI usado para criar a URL
  • um componente TIdSSLIOHandlerSocketOpenSSL que deverá fornecer a conexão segura. Os DLLs necessários estão na pasta binário.

O site também requer autenticação e eu incluído o usuário / passe na URL, como no exemplo abaixo. Em suma este é o código:

URI := TIdURI.Create('https://test.example.com/');
URI.Username := ParamUserName;
URI.Password := ParamPassword;

HTTP := TIdHTTP.Create(nil);
if URI.Protocol = 'https' then
begin
  IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  IOHandler.SSLOptions.Method := sslvSSLv3;
  HTTP.IOHandler := IOHandler;
end;

HTTP.Get(URI.GetFullURI([ofAuthInfo]), FileStream);

Usando este código eu recebo uma exceção "Leia Timeout" EIdReadTimeout muito rápido. Testando o URL em um navegador funciona sem problema. Algumas ideias sobre o que está faltando ou o que eu fiz de errado?

Foi útil?

Solução

Eu finalmente abandonado Indy e OpenSSL e usado WinInet para download. Este é o código que funcionou para mim:

function Download(URL, User, Pass, FileName: string): Boolean;
const
  BufferSize = 1024;
var
  hSession, hURL: HInternet;
  Buffer: array[1..BufferSize] of Byte;
  BufferLen: DWORD;
  F: File;
begin
   Result := False;
   hSession := InternetOpen('', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ;

   // Establish the secure connection
   InternetConnect (
     hSession,
     PChar(FullURL),
     INTERNET_DEFAULT_HTTPS_PORT,
     PChar(User),
     PChar(Pass),
     INTERNET_SERVICE_HTTP,
     0,
     0
   );

  try
    hURL := InternetOpenURL(hSession, PChar(URL), nil, 0, 0, 0) ;
    try
      AssignFile(f, FileName);
      Rewrite(f,1);
      try
        repeat
          InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ;
          BlockWrite(f, Buffer, BufferLen)
        until BufferLen = 0;
      finally
        CloseFile(f) ;
        Result := True;
      end;
    finally
      InternetCloseHandle(hURL)
    end
  finally
    InternetCloseHandle(hSession)
  end;
end;

Outras dicas

Eu vi a mesma coisa. Definir o TIdHTTP.ReadTimeout a zero corrige o problema para mim.

...
HTTP.IOHandler := IOHandler;
HTTP.ReadTimeout := 0;

Todas as funções SSL relacionado para conexões seguras falhará a menos que algumas bibliotecas adicionais são instalados corretamente.

1.) Fazer download bibliotecas

2.) Descompacte o arquivo e copiar ambas as DLLs para a pasta do projeto (ou em algum lugar no caminho de seu sistema)

com que o código da questão funciona bem para mim.

- reinhard

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top