使用 SSL/TSL 从 url 获取图像
GET Image from url with SSL/TSL
我的应用程序自动填充了将近 30 个字段,只留下少数字段供用户和验证码填写。
我需要从 url 获取并显示验证码。
我尝试了不同的方法,但 none 可以按我的需要工作。
url 是 captcha link
用chrome你会直接得到图像,用IE你会得到一个文件来下载。
第一次尝试
使用 WebBrowser 控件打开 url
如果您尝试使用 WebBrowser 打开 url,您将开始下载文件
如果您将其保存为 cap.gif 或 JPG,您将获得正确的图像。
此时我正在尝试自动下载任务以避免为用户显示下载对话框。
像其他 SO 回答一样Download file and automatically save it to folder 我尝试处理 WebBrowser 导航
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
e.Cancel = true;
WebClient client = new WebClient();
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
client.DownloadDataAsync(e.Url);
}
或直接使用 WebClient
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadFileAsync(new Uri(url), filepath);
在结果的回调中,您将得到空的图像文件(0 字节);
如果您查看 AsyncCompletedEventArgs e,它会生成关于 SSL/TSL 的错误。
The request was aborted: Could not create SSL/TLS secure channel.
in System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
in System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
in System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)
第二次尝试
将 SSL/TSL 堆栈作为 SO 答案包含到 WebClient The request was aborted: Could not create SSL/TLS secure channel
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AllwaysGoodCertificate);
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadFileAsync(new Uri(captchaUrl), filepath);
这将 return 在回调时出现同样的错误
第三次尝试
从 WebBrowser 控件获取图像并将标签转换为 PictureBox
如果我尝试在主页内容表单中提取图像,它允许我获取图像
按照 SO 回答 How to copy the loaded image in webbrowser to picturebox
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
public Bitmap CaptureWindow(Control ctl)
{
//Bitmap bmp = new Bitmap(ctl.Width, ctl.Height); // includes borders
Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height); // content only
using (Graphics graphics = Graphics.FromImage(bmp))
{
IntPtr hDC = graphics.GetHdc();
try { PrintWindow(ctl.Handle, hDC, (uint)0); }
finally { graphics.ReleaseHdc(hDC); }
}
return bmp;
}
//Methods to get Co-ordinates Of an Element in your webbrowser
public int getXoffset(HtmlElement el)
{
int xPos = el.OffsetRectangle.Left;
HtmlElement tempEl = el.OffsetParent;
while (tempEl != null)
{
xPos += tempEl.OffsetRectangle.Left;
tempEl = tempEl.OffsetParent;
}
return xPos;
}
public int getYoffset(HtmlElement el)
{
int yPos = el.OffsetRectangle.Top;
HtmlElement tempEl = el.OffsetParent;
while (tempEl != null)
{
yPos += tempEl.OffsetRectangle.Top;
tempEl = tempEl.OffsetParent;
}
return yPos;
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// get captcha
HtmlElement el = webBrowser1.Document.GetElementById("imgCaptcha");
IHTMLImgElement img = (IHTMLImgElement)el.DomElement;
Bitmap bmp = new Bitmap(img.width, img.height);
int CaptchaWidth = getXoffset(el);
int CaptchaHeight = getYoffset(el);
Rectangle rect = new Rectangle(CaptchaWidth, CaptchaHeight, img.width, img.height);
// with this image il always blank
//webBrowser1.DrawToBitmap(bmp, rect);
Bitmap bitmap = CaptureWindow(webBrowser1);
Bitmap croppedImage = bitmap.Clone(rect, System.Drawing.Imaging.PixelFormat.Undefined);
pictureBox1.BackgroundImage = croppedImage;
}
这工作正常,但不幸的是,这只有在您有 WebBrowser 控件可见时才有效...:(
如有任何建议,我们将不胜感激。
经过一些变通后,我发现了一个关于 SSL 的问题,服务器进程协议 TSL 1.2 而不是 SSL3
只需替换
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
现在 WebClient 运行良好,但在给自己一个正确答案之前,我会等待其他人是否有其他实现。
我要做的更改是使用 async/await 这样我就不必担心设置 WebClient 的 DownloadFileCompleted
这部分和你一样,
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
使用异步方法
public async Task DownloadIt(string url ,string filename)
{
using (var client = new WebClient())
{
await client.DownloadFileTaskAsync(new Uri(url), filename);
}
}
需要的时候就这样调用它。
await DownloadIt("https://www.com", @"C:\Path\To\Save");
我的应用程序自动填充了将近 30 个字段,只留下少数字段供用户和验证码填写。
我需要从 url 获取并显示验证码。
我尝试了不同的方法,但 none 可以按我的需要工作。
url 是 captcha link
用chrome你会直接得到图像,用IE你会得到一个文件来下载。
第一次尝试
使用 WebBrowser 控件打开 url 如果您尝试使用 WebBrowser 打开 url,您将开始下载文件 如果您将其保存为 cap.gif 或 JPG,您将获得正确的图像。
此时我正在尝试自动下载任务以避免为用户显示下载对话框。
像其他 SO 回答一样Download file and automatically save it to folder 我尝试处理 WebBrowser 导航
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
e.Cancel = true;
WebClient client = new WebClient();
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
client.DownloadDataAsync(e.Url);
}
或直接使用 WebClient
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadFileAsync(new Uri(url), filepath);
在结果的回调中,您将得到空的图像文件(0 字节);
如果您查看 AsyncCompletedEventArgs e,它会生成关于 SSL/TSL 的错误。
The request was aborted: Could not create SSL/TLS secure channel.
in System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
in System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
in System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)
第二次尝试
将 SSL/TSL 堆栈作为 SO 答案包含到 WebClient The request was aborted: Could not create SSL/TLS secure channel
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AllwaysGoodCertificate);
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadFileAsync(new Uri(captchaUrl), filepath);
这将 return 在回调时出现同样的错误
第三次尝试 从 WebBrowser 控件获取图像并将标签转换为 PictureBox
如果我尝试在主页内容表单中提取图像,它允许我获取图像 按照 SO 回答 How to copy the loaded image in webbrowser to picturebox
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
public Bitmap CaptureWindow(Control ctl)
{
//Bitmap bmp = new Bitmap(ctl.Width, ctl.Height); // includes borders
Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height); // content only
using (Graphics graphics = Graphics.FromImage(bmp))
{
IntPtr hDC = graphics.GetHdc();
try { PrintWindow(ctl.Handle, hDC, (uint)0); }
finally { graphics.ReleaseHdc(hDC); }
}
return bmp;
}
//Methods to get Co-ordinates Of an Element in your webbrowser
public int getXoffset(HtmlElement el)
{
int xPos = el.OffsetRectangle.Left;
HtmlElement tempEl = el.OffsetParent;
while (tempEl != null)
{
xPos += tempEl.OffsetRectangle.Left;
tempEl = tempEl.OffsetParent;
}
return xPos;
}
public int getYoffset(HtmlElement el)
{
int yPos = el.OffsetRectangle.Top;
HtmlElement tempEl = el.OffsetParent;
while (tempEl != null)
{
yPos += tempEl.OffsetRectangle.Top;
tempEl = tempEl.OffsetParent;
}
return yPos;
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// get captcha
HtmlElement el = webBrowser1.Document.GetElementById("imgCaptcha");
IHTMLImgElement img = (IHTMLImgElement)el.DomElement;
Bitmap bmp = new Bitmap(img.width, img.height);
int CaptchaWidth = getXoffset(el);
int CaptchaHeight = getYoffset(el);
Rectangle rect = new Rectangle(CaptchaWidth, CaptchaHeight, img.width, img.height);
// with this image il always blank
//webBrowser1.DrawToBitmap(bmp, rect);
Bitmap bitmap = CaptureWindow(webBrowser1);
Bitmap croppedImage = bitmap.Clone(rect, System.Drawing.Imaging.PixelFormat.Undefined);
pictureBox1.BackgroundImage = croppedImage;
}
这工作正常,但不幸的是,这只有在您有 WebBrowser 控件可见时才有效...:(
如有任何建议,我们将不胜感激。
经过一些变通后,我发现了一个关于 SSL 的问题,服务器进程协议 TSL 1.2 而不是 SSL3
只需替换
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
现在 WebClient 运行良好,但在给自己一个正确答案之前,我会等待其他人是否有其他实现。
我要做的更改是使用 async/await 这样我就不必担心设置 WebClient 的 DownloadFileCompleted
这部分和你一样,
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
使用异步方法
public async Task DownloadIt(string url ,string filename)
{
using (var client = new WebClient())
{
await client.DownloadFileTaskAsync(new Uri(url), filename);
}
}
需要的时候就这样调用它。
await DownloadIt("https://www.com", @"C:\Path\To\Save");