使用 Indy 下载 https 图像 Delphi
Download https image with Indy for Delphi
我看过很多关于如何将 http 图像下载到内存流的帖子,但我在抓取 https 图像时遇到了问题。
我希望它就像放入 SSL 处理程序一样简单,但我不断收到以下错误:
Error connecting with SSL. error:14094410:SSL reourtines:SSL3_READ_BYTES:sslv3 alert handshake failure.
我认为我一直在使用的示例站点使用 SSLv3。
https://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg
令人讨厌的是 JSON 实际上 returns 一个 http 节点,但它被重定向到 https 版本
https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY
{
"copyright": "Steve Mazlin",
"date": "2017-02-02",
"explanation": "An example of violence on a cosmic scale, enormous elliptical galaxy NGC 1316 lies about 75 million light-years away toward Fornax, the southern constellation of the Furnace. Investigating the startling sight, astronomers suspect the giant galaxy of colliding with smaller neighbor NGC 1317 seen just above, causing far flung loops and shells of stars. Light from their close encounter would have reached Earth some 100 million years ago. In the deep, sharp image, the central regions of NGC 1316 and NGC 1317 appear separated by over 100,000 light-years. Complex dust lanes visible within also indicate that NGC 1316 is itself the result of a merger of galaxies in the distant past. Found on the outskirts of the Fornax galaxy cluster, NGC 1316 is known as Fornax A. One of the visually brightest of the Fornax cluster galaxies it is one of the strongest and largest radio sources with radio emission extending well beyond this telescopic field-of-view, over several degrees on the sky. Participate: Take an Aesthetics & Astronomy Survey",
"hdurl": "http://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker.jpg",
"media_type": "image",
"service_version": "v1",
"title": "NGC 1316: After Galaxies Collide",
"url": "http://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg"
}
有什么想法吗?
旁注:我曾尝试将 SSL 版本更改为 sslvTLSv1_1
和 sslvTLSv1_2
但没有成功。
function TUrlImageReader.ReadImage: TMemoryStream;
var
ImgMS: TMemoryStream;
ImgHTTP: TIdHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
ImgMS := TMemoryStream.Create;
SSLHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
ImgHTTP:=TIdHTTP.Create(nil);
ImgHTTP.IOHandler:=SSLHandler;
SSLHandler.SSLOptions.Method:=sslvSSLv3;
try
try
ImgHTTP.Get(FURL, ImgMS);
except
on E: EIdHTTPProtocolException do
ImgMS.Clear;
end;
finally
ImgHTTP.Free;
SSLHandler.Free;
end;
ImgMS.Position := 0;
Result := ImgMS;
end;
确保您使用的是 up-to-date 版本的 Indy 10,其中包含处理 TLS 1.2 的所有最新修复程序。使用当前版本,当我将 SSLOptions.Method
设置为 sslvTLSv1_1
或 sslvTLSv1_2
时(以及当我将 SSLOptions.SSLVersions
设置为[sslvTLSv1_1, sslvTLSv1_2]
)。图片下载正确。
但是,请注意您的代码中存在内存泄漏。如果出现 除了 IdHTTPProtocolException
之外的任何异常,则您不会释放 TMemoryStream
对象。您的代码应该看起来更像这样:
function TUrlImageReader.ReadImage: TMemoryStream;
var
ImgHTTP: TIdHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
Result := TMemoryStream.Create;
try
ImgHTTP := TIdHTTP.Create(nil);
try
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(ImgHTTP);
SSLHandler.SSLOptions.Method := sslvTLSv1_1; // or sslvTLSv1_2
// or:
// SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_1, sslvTLSv1_2];
ImgHTTP.IOHandler := SSLHandler;
try
ImgHTTP.Get('https://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg', Result);
except
on E: EIdHTTPProtocolException do
Result.Clear;
end;
finally
ImgHTTP.Free;
end;
Result.Position := 0;
except
Result.Free;
raise;
end;
end;
此外,从技术上讲,您不需要 Clear
流来响应 EIdHTTPProtocolException
,因为不会向其中写入任何内容,任何响应数据都会被 [=21 静默丢弃=] 因为您没有在 TIdHTTP.HTTPOptions
属性.
中启用 hoNoProtocolErrorException
和 hoWantProtocolErrorContent
标志
为了完全避免捕获 EIdHTTPProtocolException
,您可以单独启用 hoNoProtocolErrorException
标志,例如:
function TUrlImageReader.ReadImage: TMemoryStream;
var
ImgHTTP: TIdHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
Result := TMemoryStream.Create;
try
ImgHTTP := TIdHTTP.Create(nil);
try
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(ImgHTTP);
SSLHandler.SSLOptions.Method := sslvTLSv1_1; // or sslvTLSv1_2
// or:
// SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_1, sslvTLSv1_2];
ImgHTTP.IOHandler := SSLHandler;
ImgHTTP.HTTPOptions := ImgHTTP.HTTPOptions + [hoNoProtocolErrorException];
ImgHTTP.Get('https://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg', Result);
finally
ImgHTTP.Free;
end;
Result.Position := 0;
except
Result.Free;
raise;
end;
end;
我看过很多关于如何将 http 图像下载到内存流的帖子,但我在抓取 https 图像时遇到了问题。
我希望它就像放入 SSL 处理程序一样简单,但我不断收到以下错误:
Error connecting with SSL. error:14094410:SSL reourtines:SSL3_READ_BYTES:sslv3 alert handshake failure.
我认为我一直在使用的示例站点使用 SSLv3。
https://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg
令人讨厌的是 JSON 实际上 returns 一个 http 节点,但它被重定向到 https 版本
https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY
{
"copyright": "Steve Mazlin",
"date": "2017-02-02",
"explanation": "An example of violence on a cosmic scale, enormous elliptical galaxy NGC 1316 lies about 75 million light-years away toward Fornax, the southern constellation of the Furnace. Investigating the startling sight, astronomers suspect the giant galaxy of colliding with smaller neighbor NGC 1317 seen just above, causing far flung loops and shells of stars. Light from their close encounter would have reached Earth some 100 million years ago. In the deep, sharp image, the central regions of NGC 1316 and NGC 1317 appear separated by over 100,000 light-years. Complex dust lanes visible within also indicate that NGC 1316 is itself the result of a merger of galaxies in the distant past. Found on the outskirts of the Fornax galaxy cluster, NGC 1316 is known as Fornax A. One of the visually brightest of the Fornax cluster galaxies it is one of the strongest and largest radio sources with radio emission extending well beyond this telescopic field-of-view, over several degrees on the sky. Participate: Take an Aesthetics & Astronomy Survey",
"hdurl": "http://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker.jpg",
"media_type": "image",
"service_version": "v1",
"title": "NGC 1316: After Galaxies Collide",
"url": "http://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg"
}
有什么想法吗?
旁注:我曾尝试将 SSL 版本更改为 sslvTLSv1_1
和 sslvTLSv1_2
但没有成功。
function TUrlImageReader.ReadImage: TMemoryStream;
var
ImgMS: TMemoryStream;
ImgHTTP: TIdHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
ImgMS := TMemoryStream.Create;
SSLHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
ImgHTTP:=TIdHTTP.Create(nil);
ImgHTTP.IOHandler:=SSLHandler;
SSLHandler.SSLOptions.Method:=sslvSSLv3;
try
try
ImgHTTP.Get(FURL, ImgMS);
except
on E: EIdHTTPProtocolException do
ImgMS.Clear;
end;
finally
ImgHTTP.Free;
SSLHandler.Free;
end;
ImgMS.Position := 0;
Result := ImgMS;
end;
确保您使用的是 up-to-date 版本的 Indy 10,其中包含处理 TLS 1.2 的所有最新修复程序。使用当前版本,当我将 SSLOptions.Method
设置为 sslvTLSv1_1
或 sslvTLSv1_2
时(以及当我将 SSLOptions.SSLVersions
设置为[sslvTLSv1_1, sslvTLSv1_2]
)。图片下载正确。
但是,请注意您的代码中存在内存泄漏。如果出现 除了 IdHTTPProtocolException
之外的任何异常,则您不会释放 TMemoryStream
对象。您的代码应该看起来更像这样:
function TUrlImageReader.ReadImage: TMemoryStream;
var
ImgHTTP: TIdHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
Result := TMemoryStream.Create;
try
ImgHTTP := TIdHTTP.Create(nil);
try
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(ImgHTTP);
SSLHandler.SSLOptions.Method := sslvTLSv1_1; // or sslvTLSv1_2
// or:
// SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_1, sslvTLSv1_2];
ImgHTTP.IOHandler := SSLHandler;
try
ImgHTTP.Get('https://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg', Result);
except
on E: EIdHTTPProtocolException do
Result.Clear;
end;
finally
ImgHTTP.Free;
end;
Result.Position := 0;
except
Result.Free;
raise;
end;
end;
此外,从技术上讲,您不需要 Clear
流来响应 EIdHTTPProtocolException
,因为不会向其中写入任何内容,任何响应数据都会被 [=21 静默丢弃=] 因为您没有在 TIdHTTP.HTTPOptions
属性.
hoNoProtocolErrorException
和 hoWantProtocolErrorContent
标志
为了完全避免捕获 EIdHTTPProtocolException
,您可以单独启用 hoNoProtocolErrorException
标志,例如:
function TUrlImageReader.ReadImage: TMemoryStream;
var
ImgHTTP: TIdHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
Result := TMemoryStream.Create;
try
ImgHTTP := TIdHTTP.Create(nil);
try
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(ImgHTTP);
SSLHandler.SSLOptions.Method := sslvTLSv1_1; // or sslvTLSv1_2
// or:
// SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_1, sslvTLSv1_2];
ImgHTTP.IOHandler := SSLHandler;
ImgHTTP.HTTPOptions := ImgHTTP.HTTPOptions + [hoNoProtocolErrorException];
ImgHTTP.Get('https://apod.nasa.gov/apod/image/1702/NGC1316_MazlinKellerMenaker1024d.jpg', Result);
finally
ImgHTTP.Free;
end;
Result.Position := 0;
except
Result.Free;
raise;
end;
end;