从 CEFSharp 的缓存中读取文件
Read a file from the cache in CEFSharp
我需要导航到最终包含 .pdf 文件的网站,并且我想将该文件保存在本地。我正在使用 CEFSharp 来执行此操作。该网站的性质是,一旦 .pdf 出现在浏览器中,就无法再次访问。出于这个原因,我想知道如果在浏览器中显示 .pdf 后,是否有办法访问缓存中该文件的源代码?
我已经尝试实施 IDownloadHandler 并且有效,但您必须单击嵌入式 .pdf 上的保存按钮。我正在努力解决这个问题。
好的,这就是我如何让它工作的。 CEFSharp 中有一个功能允许您过滤传入的 Web 响应。因此,这使您可以完全访问传入流。我的解决方案有点脏,效率不是特别高,但它适用于我的情况。如果有人看到更好的方法,我愿意提出建议。为了让我的代码正常工作,我必须假设两件事。
- 每次下载新页面时调用 GetResourceResponseFilter。
- PDF 是导航过程中最后要下载的东西。
从此处找到的 CEF 最小示例开始:https://github.com/cefsharp/CefSharp.MinimalExample
我用的是WinForms版本。在表单定义中实现 IRequestHandler 和 IResponseFilter 如下:
public partial class BrowserForm : Form, IRequestHandler, IResponseFilter
{
public readonly ChromiumWebBrowser browser;
public BrowserForm(string url)
{
InitializeComponent();
browser = new ChromiumWebBrowser(url)
{
Dock = DockStyle.Fill,
};
toolStripContainer.ContentPanel.Controls.Add(browser);
browser.BrowserSettings.FileAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings.WebSecurity = CefState.Disabled;
browser.BrowserSettings.Javascript = CefState.Enabled;
browser.LoadingStateChanged += OnLoadingStateChanged;
browser.ConsoleMessage += OnBrowserConsoleMessage;
browser.StatusMessage += OnBrowserStatusMessage;
browser.TitleChanged += OnBrowserTitleChanged;
browser.AddressChanged += OnBrowserAddressChanged;
browser.FrameLoadEnd += browser_FrameLoadEnd;
browser.LifeSpanHandler = this;
browser.RequestHandler = this;
声明和最后两行对于这个解释来说是最重要的。我使用此处找到的模板实现了 IRequestHandler:
https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/RequestHandler.cs
除了我按如下方式实现的 GetResourceResponseFilter 之外,我将所有内容更改为它推荐的默认值:
IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
if (request.Url.EndsWith(".pdf"))
return this;
return null;
}
然后我按如下方式实现了 IResponseFilter:
FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
{
BinaryWriter sw;
if (dataIn == null)
{
dataInRead = 0;
dataOutWritten = 0;
return FilterStatus.Done;
}
dataInRead = dataIn.Length;
dataOutWritten = Math.Min(dataInRead, dataOut.Length);
byte[] buffer = new byte[dataOutWritten];
int bytesRead = dataIn.Read(buffer, 0, (int)dataOutWritten);
string s = System.Text.Encoding.UTF8.GetString(buffer);
if (s.StartsWith("%PDF"))
File.Delete(pdfFileName);
sw = new BinaryWriter(File.Open(pdfFileName, FileMode.Append));
sw.Write(buffer);
sw.Close();
dataOut.Write(buffer, 0, bytesRead);
return FilterStatus.Done;
}
bool IResponseFilter.InitFilter()
{
return true;
}
我发现PDF在加载时实际上下载了两次。在任何情况下,页面开头都可能有 header 信息和其他信息。当我得到一个以 %PDF 开头的流片段时,我知道它是 PDF 的开头,所以我删除了该文件以丢弃可能存在的任何先前内容。否则,我只是将每个段附加到文件末尾。从理论上讲,在您导航到另一个 PDF 之前,PDF 文件是安全的,但我的建议是为了安全起见,在页面加载后立即对该文件进行一些操作。
我需要导航到最终包含 .pdf 文件的网站,并且我想将该文件保存在本地。我正在使用 CEFSharp 来执行此操作。该网站的性质是,一旦 .pdf 出现在浏览器中,就无法再次访问。出于这个原因,我想知道如果在浏览器中显示 .pdf 后,是否有办法访问缓存中该文件的源代码?
我已经尝试实施 IDownloadHandler 并且有效,但您必须单击嵌入式 .pdf 上的保存按钮。我正在努力解决这个问题。
好的,这就是我如何让它工作的。 CEFSharp 中有一个功能允许您过滤传入的 Web 响应。因此,这使您可以完全访问传入流。我的解决方案有点脏,效率不是特别高,但它适用于我的情况。如果有人看到更好的方法,我愿意提出建议。为了让我的代码正常工作,我必须假设两件事。
- 每次下载新页面时调用 GetResourceResponseFilter。
- PDF 是导航过程中最后要下载的东西。
从此处找到的 CEF 最小示例开始:https://github.com/cefsharp/CefSharp.MinimalExample
我用的是WinForms版本。在表单定义中实现 IRequestHandler 和 IResponseFilter 如下:
public partial class BrowserForm : Form, IRequestHandler, IResponseFilter
{
public readonly ChromiumWebBrowser browser;
public BrowserForm(string url)
{
InitializeComponent();
browser = new ChromiumWebBrowser(url)
{
Dock = DockStyle.Fill,
};
toolStripContainer.ContentPanel.Controls.Add(browser);
browser.BrowserSettings.FileAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings.WebSecurity = CefState.Disabled;
browser.BrowserSettings.Javascript = CefState.Enabled;
browser.LoadingStateChanged += OnLoadingStateChanged;
browser.ConsoleMessage += OnBrowserConsoleMessage;
browser.StatusMessage += OnBrowserStatusMessage;
browser.TitleChanged += OnBrowserTitleChanged;
browser.AddressChanged += OnBrowserAddressChanged;
browser.FrameLoadEnd += browser_FrameLoadEnd;
browser.LifeSpanHandler = this;
browser.RequestHandler = this;
声明和最后两行对于这个解释来说是最重要的。我使用此处找到的模板实现了 IRequestHandler: https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/RequestHandler.cs 除了我按如下方式实现的 GetResourceResponseFilter 之外,我将所有内容更改为它推荐的默认值:
IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
if (request.Url.EndsWith(".pdf"))
return this;
return null;
}
然后我按如下方式实现了 IResponseFilter:
FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
{
BinaryWriter sw;
if (dataIn == null)
{
dataInRead = 0;
dataOutWritten = 0;
return FilterStatus.Done;
}
dataInRead = dataIn.Length;
dataOutWritten = Math.Min(dataInRead, dataOut.Length);
byte[] buffer = new byte[dataOutWritten];
int bytesRead = dataIn.Read(buffer, 0, (int)dataOutWritten);
string s = System.Text.Encoding.UTF8.GetString(buffer);
if (s.StartsWith("%PDF"))
File.Delete(pdfFileName);
sw = new BinaryWriter(File.Open(pdfFileName, FileMode.Append));
sw.Write(buffer);
sw.Close();
dataOut.Write(buffer, 0, bytesRead);
return FilterStatus.Done;
}
bool IResponseFilter.InitFilter()
{
return true;
}
我发现PDF在加载时实际上下载了两次。在任何情况下,页面开头都可能有 header 信息和其他信息。当我得到一个以 %PDF 开头的流片段时,我知道它是 PDF 的开头,所以我删除了该文件以丢弃可能存在的任何先前内容。否则,我只是将每个段附加到文件末尾。从理论上讲,在您导航到另一个 PDF 之前,PDF 文件是安全的,但我的建议是为了安全起见,在页面加载后立即对该文件进行一些操作。