使用https:// - Delphi下载协议时出错

时间:2015-08-12 21:40:31

标签: delphi delphi-xe5

我想知道如何在Delphi中使用协议https://下载文件。我正在使用idhttp,但是当我点击下载时会返回错误代码:

series = pd.Series()
for l in b_list:
    series.append(l.get_results())
    print(l.get_results())
    count += 1
print(series)

单击按钮后,几秒钟就会终止应用程序。

-1

enter image description here

2 个答案:

答案 0 :(得分:5)

首先,您的错误处理是错误的。您只显示TIdHTTP.ResponseCode属性值,而不显示任何其他值。 ResponseCode具有有意义值的唯一例外是EIdHTTPProtocolException(即使这样,您也应该从EIdHTTPProtocolException.ErrorCode属性获取值)。 ResponseCode不太可能在任何其他例外中填充,在您的情况下显然就是这种情况。由于您将遇到捕获不同类型异常的麻烦,您应该显示对这些特定类型有意义的错误消息,例如:

except
  on E: EIdHTTPProtocolException do begin
    ShowMessage('HTTP request failed'#13 + IntToStr(E.ErrorCode) + ' ' + E.Message);
  end;
  on E: EIdOpenSSLAPISSLError do
  begin
    ShowMessage('OpenSSL API failure'#13 + E.ClassName + #13'Result Code: ' + IntToStr(E.RetCode) + #13'Error Code: ' + IntToStr(E.ErrorCode));
  end;
  on E: EIdOpenSSLAPICryptoError do
  begin
    ShowMessage('OpenSSL crypto failure'#13 + E.ClassName + #13'Error Code: ' + IntToStr(E.ErrorCode));
  end;
  on E: EIdOpenSSLError do
  begin
    ShowMessage('Unknown OpenSSL error'#13 + E.ClassName + #13 + E.Message);
  end;
  on E: EIdSocketError do begin
    ShowMessage('Socket error'#13 + E.ClassName + #13'Error Code: ' + IntToStr(E.LastError) + ' ' + E.Message);
  end;
  on E: Exception do begin
    ShowMessage('Unexpected error'#13 + E.ClassName + #13 + E.Message);
  end;
end;

其次,如果您在桌面系统(Windows或OSX)上运行应用程序,则会泄漏TIdSSLIOHandlerSocketOpenSSL对象,因为您没有为其分配Owner,{{1不承担它的所有权。如果您在移动系统上运行应用程序(iOS或Android),则代码将崩溃,因为没有引用在创建TIdHTTP对象后保持活动状态。 TIdSSLIOHandlerSocketOpenSSLTIdTCPConnection.IOHandler属性在这些平台上使用 weak 引用,因此对象的引用计数不会增加,并且最终会被过早销毁。如果您未指定TIdTCPConnection.Socket,则需要明确释放该对象,例如在Zam的答案演示的Owner中。

或者,如果您使用的是Indy的最新版本,则可以利用今年早些时候添加到try/finally的新HTTPS功能,这样您就不必创建{ {1}}显式对象:

New HTTPS functionality for TIdHTTP

第三,关于你得到的实际例外,TIdHTTP正是它的名字所暗示的。无法加载OpenSSL库。这意味着无法找到DLL(libeay32.dll和ssleay32.dll),或者它们不会导出Indy查找的所有内容。您可以调用IOHandler单元中的EIdOSSLCouldNotLoadSSLLibrary函数来找出无法加载OpenSSL的原因:

WhichFailedToLoad()

确保安装了OpenSSL DLL的兼容版本,无论是在应用程序的文件夹中,在OS搜索路径上的文件夹中,还是在通过其IdSSLOpenSSLHeaders功能指定给Indy的文件夹中。 except //... on E: EIdOSSLCouldNotLoadSSLLibrary do begin ShowMessage('Could not load OpenSSL library'#13'Failed to load: ' + WhichFailedToLoad); end; //... end; 单位。通常,您应该努力始终使用可用的最新OpenSSL版本(在撰写本文时,它是1.0.2d)。

答案 1 :(得分:2)

首先,您没有使用所有必需的单位。

uses
    IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL;

这是工作样本,在Delphi XE7和XE8下测试。 FMX平台。

var
    FResponse: TMemoryStream;

procedure Load;
var
    LUrl: String;
    IdHTTP: TIdHTTP;
    IdSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
    LUrl := 'https://google.lv/';

    IdHTTP := TIdHTTP.Create(nil);
    try
      IdSSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        IdHTTP.IOHandler := IdSSLIOHandlerSocketOpenSSL;
        try
          IdHTTP.Get(LUrl, FResponse);
        except
          { We are hiding error }
        end;
      finally
        IdSSLIOHandlerSocketOpenSSL.Free;
      end;
    finally
      IdHTTP.Free;
    end;
end;

不要忘记使用FResponse := TMemoryStream.Create;

创建FResponse

和last:确保使用正确的OpenSSL库 对于我正在使用的Indy 10.6.1.5182:

[WIN] [x86] OpenSSL共享库1.0.1.7; OpenSSL Toolkit 1.0.1g;

libeay32.dll
1 281 024 bytes

ssleay32.dll
270 336 bytes

[WIN] [x64] OpenSSL共享库1.0.1.7; OpenSSL Toolkit 1.0.1g;

libeay32.dll
1 817 088 bytes

ssleay32.dll
371 200 bytes