从CEFSharp中的缓存中读取文件



我需要导航到一个最终包含.pdf文件的网站,我想将该文件保存在本地。我正在使用CEFSharp来执行此操作。该网站的性质是,一旦.pdf出现在浏览器中,就无法再次访问。出于这个原因,我想知道一旦你在浏览器中显示了.pdf,是否有办法访问缓存中该文件的源?

我已经尝试过实现IDownloadHandler,这是有效的,但你必须点击嵌入式.pdf上的保存按钮。我正在努力解决这个问题。

好吧,下面是我如何让它工作的。CEFSharp中有一个功能,允许您过滤传入的web响应。因此,这使您能够完全访问传入流。我的解决方案有点脏,不是特别有效,但它适用于我的情况。如果有人看到更好的方法,我愿意接受建议。为了使代码正常工作,我必须假设两件事。

  1. 每次下载新页面时都会调用GetResourceResponseFilter
  2. 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在加载时实际上下载了两次。在任何情况下,页面开头都可能有标题信息以及其他信息。当我得到一个以%PDF开头的流片段时,我知道这是PDF的开头,所以我删除了该文件,以丢弃可能存在的任何以前的内容。否则,我只是不断地将每个片段附加到文件的末尾。理论上,在你导航到另一个PDF之前,PDF文件是安全的,但我的建议是在页面加载后立即对文件进行处理,以确保安全。

相关内容

  • 没有找到相关文章

最新更新