2016-05-16 121 views
0

我需要導航到最終包含.pdf文件的網站,並且我想在本地保存該文件。我正在使用CEFSharp來執行此操作。這個網站的性質是這樣的,一旦.pdf出現在瀏覽器中,它不能被再次訪問。出於這個原因,我想知道如果瀏覽器中顯示了.pdf,是否有方法可以訪問緩存中該文件的源代碼?從CEFSharp中的緩存中讀取文件

我已經嘗試過實現IDownloadHandler並且可以工作,但是您必須單擊嵌入式.pdf上的保存按鈕。我試圖解決這個問題。

+0

'CEF'沒有提供訪問'cache'的方法(你可能直接讀取'db',儘管我從未嘗試過)。你可以實現一個'ResourceHandler'並自己下載文件,並在本地進行緩存。根據您使用的分支,「ResourceHandler」的實現稍有不同。請參閱https://github.com/cefsharp/CefSharp/blob/cefsharp/49/CefSharp.Example/FlashResourceHandler.cs#L22應該是一個起點,如果您使用舊版本,只需切換分支以查看不同的版本。 – amaitland

+0

我在使用.Net WebBrowser的這個項目的早期版本中嘗試了這種方法。我碰到的問題是,創建的HTMLRequest沒有cookies或任何安全信息來訪問.pdf。有沒有辦法將瀏覽器中緩存的安全信息傳遞給HTMLRequest? –

+1

我想你可以查詢cookie存儲,雖然這變得越來越複雜。還有另一種選擇,雖然很新,並沒有特別好的測試。見https://github.com/cefsharp/CefSharp/pull/1519 – amaitland

回答

8

好的,這是我如何得到它的工作。 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文件之前是安全的,但我的建議是在頁面加載後立即對文件執行某些操作以保證安全。

+0

完美的解決方案 –