我使用 URLDownloadToFile 从 URL 下载文件。正常情况下效果很好。
但是,当我尝试从 Amazon CDN 下载文件时,总是会失败。
网址是:https://download.datanumen.com/downloads/file/dexr.exe,我可以从Chrome或FireFox手动下载,没有问题。
我的代码是:
// Delete the cache before calling URLDownloadToFile
DeleteUrlCacheEntry(strURL);
HRESULT hr;
hr = URLDownloadToFile(NULL, strURL, strFileName, 0, NULL);
if (hr == INET_E_DOWNLOAD_FAILURE)
hr = hr;
if (hr != S_OK)
{
_com_error err(hr);
_tprintf(_T("Error in download: %s.\r\n"), err.ErrorMessage());
}
IStream* stream;
hr = URLOpenBlockingStream(0, LPCTSTR(strURL), &stream, 0, 0);
if (hr != S_OK)
{
_com_error err(hr);
_tprintf(_T("Error in download: %s.\r\n"), err.ErrorMessage());
}
return (hr == S_OK);
结果如下:
Error in download: Unknown error 0x800C0005.
Error in download: Unknown error 0x800C0005.
由于返回错误是未知错误,我什至不知道如何修复它。
更新
我尝试使用在Delphi中下载文件中的代码来下载文件。
我的代码是:
function DownloadFile(const strURL: string; const strFileName: string): Boolean;
var
IdHTTP1: TIdHTTP;
http : TNetHTTPClient;
Stream: TMemoryStream;
Url, FileName: String;
begin
Url := 'http://www.rejbrand.se';
Filename := 'download.htm';
IdHTTP1 := TIdHTTP.Create(nil);
http := TNetHTTPClient.Create(nil);
Stream := TMemoryStream.Create;
try
//IdHTTP1.Get(strURL, Stream);
http.Get(strURL, stream);
Stream.SaveToFile(strFileName);
finally
Stream.Free;
IdHTTP1.Free;
end;
end;
使用 TIdHTTP 时,出现以下异常:
Project DLVerify.exe raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting with SSL.
error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version'.
使用 TNetHTTPClient 时,出现以下异常:
Project DLVerify.exe raised exception class ENetHTTPClientException with message 'Error sending data: (12175) A security error occurred'.
看来无法从该网址下载代码。
更新2
我尝试将 TLS 更改为 1.2 和 2.0,两者都失败,结果相同:
function DownloadFile1(const strURL: string; const strFileName: string): Boolean;
var
LHTTP: TIdHTTP;
LHandler: TIdSSLIOHandlerSocketOpenSSL;
responseFromServer, sWhichFail, sVer :string;
Stream: TMemoryStream;
begin
//ResponseMemo.Clear;
LHTTP := TIdHTTP.Create(nil);
try
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(LHTTP);
LHandler.SSLOptions.SSLVersions := [sslvSSLv2, sslvSSLv23, sslvSSLv3, sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
LHandler.SSLOptions.Mode := sslmClient;
LHandler.SSLOptions.VerifyMode := [];
LHandler.SSLOptions.VerifyDepth := 0;
LHTTP.IOHandler := LHandler;
LHTTP.AllowCookies := True;
Stream := TMemoryStream.Create;
try
//IdHTTP1.Get(strURL, Stream);
LHTTP.Get(strURL, stream);
Stream.SaveToFile(strFileName);
finally
Stream.Free;
LHTTP.Free;
end;
end;
更新3:
使用
LHandler.SSLOptions.SSLVersions := [sslvTLSv1_1,sslvTLSv1_2];
并得到一些不同的结果:
Project DLVerify.exe raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting with SSL.
error:140740BF:SSL routines:SSL23_CLIENT_HELLO:no protocols available'.
Delphi 11 Update 2 (28.0.46141.0937) 附带的
TIdHTTP
(Indy 10.6.2.0) 没有问题
implementation
uses
IdHTTP, IdSSLOpenSSL;
procedure Download;
var
http: TIdHTTP;
ssl: TIdSSLIOHandlerSocketOpenSSL;
ms: TMemoryStream;
begin
//ShowMessage(http.Version);
http := TIdHTTP.Create(nil);
ms := TMemoryStream.Create;
try
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(http);
ssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
http.IOHandler := ssl;
http.Get('https://download.datanumen.com/downloads/file/dexr.exe', ms);
ms.SaveToFile('c:\temp\dexr.exe');
finally
ms.Free;
http.Free;
end;
end;
openssl 库是 1.0.2u (1.0.2.21)。
同样适用于
THTTPClient
,没问题:
implementation
uses
System.Net.HttpClient;
procedure Download2;
var
http: THTTPClient;
ms: TMemoryStream;
begin
http := THTTPClient.Create;
ms := TMemoryStream.Create;
try
http.Get('https://download.datanumen.com/downloads/file/dexr.exe', ms);
ms.SaveToFile('c:\temp\dexr.exe');
finally
ms.Free;
http.Free;
end;
end;