2010-02-11 105 views
9

我有以下任务:使用HTTPS和身份验证下载文件。 Indy似乎要走,但由于某种原因,它迄今为止并不奏效。我在地方执行以下操作:如何使用Indy 10和OpenSSL通过HTTPS下载文件?

  • 我使用下载
  • 用于创建URL
  • 一个TIdSSLIOHandlerSocketOpenSSL组件,它应该提供安全连接TIdURI分量TIdHTTP组件。所需的DLL位于二进制文件夹中。

该网站还要求身份验证,并且我在下面的示例中包含了用户名/密码。总之这是代码:

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); 

使用这个代码,我得到一个“读超时” EIdReadTimeout例外非常快。在浏览器中测试URL是毫无问题的。任何想法什么是缺失或我做错了什么?

+0

在应用程序和服务器之间是否存在防火墙/代理? '浏览器作品'并不意味着有直接的互联网连接。 – mjn 2010-02-11 14:16:43

+0

@mjustin如果我查看浏览器设置,则没有定义代理。另外,WinInet方法在没有设置任何代理的情况下工作的事实告诉我,这不是问题。 – Tihauan 2010-02-12 08:31:24

+3

在这种情况下,请勿使用TIdURI.Username/password属性。您必须改用TIdHTTP.Username/Password属性。 – 2010-02-12 10:17:38

回答

9

我终于放弃了Indy和OpenSSL,并使用WinInet进行下载。这是为我工作的代码:除非一些其他的库都安装正确

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; 
+0

关于上面的代码的警告一句话:你应该总是使用INTERNET_FLAG_RELOAD参数来强制从服务器下载而不是缓存。所以我建议你将代码改为:hURL:= InternetOpenURL(hSession,PChar(fullURL) ,零,0,INTERNET_FLAG_RELOAD,0); – user2858981 2016-11-10 15:11:59

0

所有SSL安全连接相关的功能将失败。

1)Download libraries

2)解压缩和复制两个DLL文件到您的项目文件夹(或在您的系统的路径某处)

与从问题的代码工作正常,我。

--reinhard

+0

谢谢你的回答。我有DLL的地方,似乎他们正确加载。读取超时似乎是由别的东西引起的。 WinInet方法适用于同一台服务器。 – Tihauan 2010-02-11 13:25:53

1

我见过同样的事情。将TIdHTTP.ReadTimeout设置为零可以为我解决问题。

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

ReadTimeout = 0是默认超时值,它表示无限超时。 – 2010-02-12 10:15:47

+0

是的,但在附加IOHandler后将其设置在代码中似乎阻止了引发EIdReadTimeout异常。 (至少在我的经验中,随着Delphi的Indy版本) – jasonpenny 2010-02-12 13:20:40