简体   繁体   English

抑制 WebBrowser 控件中的保存/打开对话框

[英]Suppressing the Save/Open Dialog box in a WebBrowser control

I have a WebBrowser control that is automatically logging me into a website and attempting to download CSV data automatically.我有一个 WebBrowser 控件,它会自动将我登录到网站并尝试自动下载 CSV 数据。 Everything is working fine, except, when it tries to download the CSV data, it is popping up a dialog box, asking if I want to save the file or open it (just like in IE).一切正常,除了当它尝试下载 CSV 数据时,它会弹出一个对话框,询问我是否要保存文件或打开它(就像在 IE 中一样)。 What I am trying to do is automatically download the CSV file to a file of my choosing (or better, save the CSV file directly into a string variable).我想要做的是自动将 CSV 文件下载到我选择的文件中(或者更好的是,将 CSV 文件直接保存到字符串变量中)。 I can't seem to figure out how to suppress the dialog box and capture the download automatically.我似乎无法弄清楚如何抑制对话框并自动捕获下载。 I've search and found a few solutions, however, they don't work for me because:我已经搜索并找到了一些解决方案,但是,它们对我不起作用,因为:

1) I am now using a GUI. 1) 我现在使用 GUI。 All this is done in a class (therefore, methods such as SendKeys would not be a viable solution)所有这些都是在一个类中完成的(因此,像 SendKeys 这样的方法不是一个可行的解决方案)

2) The download comes from a secure site and requires authentication. 2) 下载来自安全站点并需要身份验证。 The WebBrowser control handles all that for me, but if I use a WebRequest and WebResponse to try to capture the download, I am no longer authenticated. WebBrowser 控件为我处理所有这些,但如果我使用 WebRequest 和 WebResponse 来尝试捕获下载,我将不再通过身份验证。

I am using C#.我正在使用 C#。 Any help would be appreciated.任何帮助,将不胜感激。

You can hook up your own IDownloadManager implementation that does download quietly. 您可以连接自己的IDownloadManager实现,它可以安静地下载。 For Windows Forms, this means you need to override the WebBrowser.CreateWebBrowserSiteBase method to provide your extended control site. 对于Windows窗体,这意味着您需要覆盖WebBrowser.CreateWebBrowserSiteBase方法以提供扩展控件站点。 Check Webbrowser Control Downloads for details. 有关详细信息,请查看Webbrowser控制下载

you can't suppress the file download dialog as that it would be a major security risk. 你不能压制文件下载对话框,因为这将是一个主要的安全风险。 I would suggest you investigate other routes to get your request authenticated if you want to make this process automatic. 如果您想自动执行此过程,我建议您调查其他路由以验证您的请求。

You can inject JavaScript to return file to your C# code from WebBrowser control and save it wherever you want without popping up the save as dialog box.您可以注入 JavaScript 以将文件从 WebBrowser 控件返回到您的 C# 代码,并将其保存在您想要的任何位置,而无需弹出另存为对话框。 Injecting JavaScript is really helpful if a website being automated requires login and implements sessions or request verifications etc.如果自动化的网站需要登录并实现会话或请求验证等,注入 JavaScript 真的很有帮助。

The logic is to inject JavaScript that downloads file as bytes (in the WebBrowser control) and then convert bytes to base64 string and return base64 string to C#.逻辑是注入以字节形式下载文件的 JavaScript(在 WebBrowser 控件中),然后将字节转换为 base64 字符串并将 base64 字符串返回到 C#。 Then C# code will convert base64 string to bytes and will save bytes as file on disk.然后 C# 代码会将 base64 字符串转换为字节,并将字节保存为磁盘上的文件。 It can be any file eg Excel or PDF etc.它可以是任何文件,例如 Excel 或 PDF 等。

Because WebBrowser control is based on Internet Explorer, so it does not support fetch API, so you have to use XMLHttpRequest.因为WebBrowser控件是基于Internet Explorer的,所以不支持fetch API,所以必须使用XMLHttpRequest。 When the page in WebBrowser control has download link ready, then inject following script into the document in WebBrowser control:当 WebBrowser 控件中的页面准备好下载链接时,将以下脚本注入 WebBrowser 控件中的文档:

string strScript = "var fileInBase64; " +
    "var oReq = new XMLHttpRequest();" +
    "            oReq.onload = function(e) {" +
    "                var buffer = oReq.response;" +
    "                //Convert response to base64 string" +
    "                var reader = new FileReader();" +
    "                reader.readAsDataURL(buffer);" +
    "                reader.onloadend = function() {" +
    "                    fileInBase64 = reader.result;//Buffer value in fileInBase64" +
    "                }" +
    "            };" +
    "            oReq.open('GET', 'downloadLink');" +
    "            oReq.responseType = 'blob';" +
    "            oReq.send(); ";
HtmlElement head = wb.Document.GetElementsByTagName("head")[0];
HtmlElement script = wb.Document.CreateElement("script");
script.SetAttribute("text", strScript);
head.AppendChild(script);

Because result from XMLHttpRequest may not be ready immediately, so to retrieve value of fileInBase64 variable inject other script after a wait of 1 or 2 seconds or add another condition (or logic) to wait until file in fileInBase64 variable is not ready.因为 XMLHttpRequest 的结果可能不会立即准备好,因此要检索 fileInBase64 变量的值,请在等待 1 或 2 秒后注入其他脚本或添加另一个条件(或逻辑)以等待 fileInBase64 变量中的文件未准备好。

string strScript = "function getBase64(){return fileInBase64;}";
HtmlElement head = wb.Document.GetElementsByTagName("head")[0];
HtmlElement script = wb.Document.CreateElement("script");
script.SetAttribute("text", strScript);
head.AppendChild(script);
object o = wb.Document.InvokeScript("getBase64");

Now object o has the file as base64 string and is ready to be saved wherever you want.现在对象 o 将文件作为 base64 字符串并准备好保存在任何你想要的地方。 Use following code to save it on disk:使用以下代码将其保存在磁盘上:

o = o.ToString().Replace("data:application/excel;base64,", ""); //replace to make a valid base64 string.
System.IO.File.WriteAllBytes("D:/file.xls", Convert.FromBase64String(o.ToString()));

For me this was the best solution to bypass save dialog box when file is downloaded from WebBrowser control.对我来说,这是从 WebBrowser 控件下载文件时绕过保存对话框的最佳解决方案。 I hope this will help others also.我希望这也能帮助其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM