首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用SSL/TSL从url获取图像

使用SSL/TSL从url获取图像
EN

Stack Overflow用户
提问于 2017-02-08 20:00:22
回答 2查看 2K关注 0票数 1

我的应用程序自动填充了几乎30个字段,只留下很少的部分供用户和captcha使用。

我需要从url获取并显示captcha。

我尝试了不同的方法,但没有一种能满足我的需要。

url为captcha链接

使用chrome,您将直接获得图像,使用IE,您将得到一个文件下载。

第一次尝试

使用WebBrowser控件打开url,如果您尝试用WebBrowser打开url,您将从文件下载开始,如果您像cap.gif或JPG一样保存它,您将得到正确的图像。

在这一点上,我试图自动下载任务,以避免显示下载对话框的用户。

和其他的一样,回答下载文件并自动保存到文件夹,我尝试处理WebBrowser导航

代码语言:javascript
复制
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

代码语言:javascript
复制
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadFileAsync(new Uri(url), filepath);

在结果的回调中,您将得到图像文件为空(0字节);

如果您查看AsyncCompletedEventArgs e,它会生成与SSL/TSL相关的错误。

代码语言:javascript
复制
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堆栈包含到WebClient,以便回答请求被中止:无法创建SSL/TLS安全通道

代码语言:javascript
复制
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);

这将在回调时返回相同的错误。

第三次尝试从WebBrowser控件获取图像并将标记转换为PictureBox

如果我尝试在主页面内容表单上提取图像,它允许我获得图像跟随,所以回答如何将webbrowser中加载的图像复制到picturebox

代码语言:javascript
复制
[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控件可见时才能工作。:(

任何建议都将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-08 23:22:02

经过一些研究,我发现了一个关于SSL的问题,即服务器进程协议tsl1.2而不是SSL3。

只需替换

代码语言:javascript
复制
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

现在WebClient运行得很好,但是在给自己一个正确的答案之前,如果其他人有其他实现,我会等待。

票数 1
EN

Stack Overflow用户

发布于 2017-02-09 00:01:01

我要做的改变是使用异步/等待,这样我就不用担心设置DownloadFileCompleted of WebClient了

这部分和你一样,

代码语言:javascript
复制
 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

使用异步方法

代码语言:javascript
复制
public async Task DownloadIt(string url ,string filename)
{
     using (var client = new WebClient())
     {
         await client.DownloadFileTaskAsync(new Uri(url), filename);
     }
}

你需要的时候就这么说吧。

代码语言:javascript
复制
await DownloadIt("https://www.com", @"C:\Path\To\Save");
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42122525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档