您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“C#怎么使用CefSharp自定義緩存”,內容詳細,步驟清晰,細節處理妥當,希望這篇“C#怎么使用CefSharp自定義緩存”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
CefSharp的默認緩存實現方式是基于Chromium的緩存機制。Chromium使用了兩種類型的緩存:內存緩存和磁盤緩存。
內存緩存是一個基于LRU(最近最少使用)算法的緩存,它緩存了最近訪問的頁面和資源。內存緩存的大小是有限的,當緩存達到最大大小時,最近最少使用的頁面和資源將被刪除。
內存緩存無法通過CefSharp.WPF的API進行設置。具體來說,Chromium會在內存中維護一個LRU(Least Recently Used)緩存,用于存儲最近訪問的網頁數據。當緩存空間不足時,Chromium會根據LRU算法自動清除最近最少使用的緩存數據,以騰出空間存儲新的數據。
在CefSharp.WPF中,我們可以通過調用Cef.GetGlobalRequestContext().ClearCacheAsync()方法來清除內存緩存中的數據。該方法會清除所有緩存數據,包括內存緩存和磁盤緩存。如果只需要清除內存緩存,可以調用Cef.GetGlobalRequestContext().ClearCache(CefCacheType.MemoryCache)方法。
需要注意的是,由于內存緩存是由Chromium自身維護的,因此我們無法直接控制其大小。如果需要控制緩存大小,可以通過設置磁盤緩存的大小來間接控制內存緩存的大小。
磁盤緩存是一個基于文件系統的緩存,它緩存了已經下載的頁面和資源。磁盤緩存的大小也是有限的,當緩存達到最大大小時,最早的頁面和資源將被刪除。
CefSharp.WPF的磁盤緩存是通過設置CefSettings中的CachePath屬性來實現的。具體來說,我們可以通過以下代碼設置磁盤緩存的路徑:
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // CachePath需要為絕對路徑 var settings = new CefSettings { CachePath = $"{AppDomain.CurrentDomain.BaseDirectory}DefaultCaches" }; Cef.Initialize(settings); } }
緩存目錄結構如下:
其中,CachePath屬性指定了磁盤緩存的路徑(絕對路徑)。如果不設置該屬性,Chromium會將緩存數據存儲在默認路徑下(通常是用戶目錄下的AppData\Local\CefSharp目錄)。
需要注意的是,磁盤緩存的大小是由Chromium自身控制的,我們可以通過設置CacheController的SetCacheLimit方法來控制緩存數據存儲在磁盤上的最大空間。該方法接受一個long類型的參數,表示緩存數據的最大大小(單位為字節)。例如,以下代碼將磁盤緩存的最大大小設置為100MB:
var cacheController = Cef.GetGlobalRequestContext().CacheController; cacheController.SetCacheLimit(100 * 1024 * 1024); // 100MB
需要注意的是,Chromium會根據LRU算法自動清除最近最少使用的緩存數據,以騰出空間存儲新的數據。因此,即使設置了緩存大小,也不能保證所有數據都會被緩存。如果需要清除磁盤緩存中的數據,可以調用Cef.GetGlobalRequestContext().ClearCacheAsync()方法。
默認的緩存站長研究不多,上面的代碼和描述通過ChatGPT搜索得來,我們來看自定義緩存的實現,默認緩存只是個引子。
這是本文介紹的重點,相對于默認緩存,自定義緩存
有以下好處:
更加靈活:可以根據應用程序的需求來靈活地配置緩存策略和緩存大小,從而更好地滿足應用程序的需求。 更好的性能:可以根據應用程序的需求和特定的場景進行配置,以獲得更好的性能。默認的緩存可能不適合某些特定的場景或者不適合您的應用程序的需求,而自定義緩存則可以根據您的需求進行調整,以獲得更好的性能。 更好的安全性:可以更好地保護用戶的隱私和安全,因為可以控制緩存中存儲的內容和緩存的生命周期。 更加可控:可以更好地控制緩存的行為,例如可以控制緩存的清除時間和清除策略,從而更好地管理緩存。 更好的兼容性:可以更好地適應不同的瀏覽器和設備,默認的緩存可能不能提供足夠的兼容性,而自定義緩存則可以根據您的需求進行調整,以提供更好的兼容性。 更加高效:可以更好地利用系統資源,例如可以使用更快的存儲設備來存儲緩存,從而提高緩存的讀寫速度。
總結:自定義緩存可以提供更好的性能、響應性、安全性和兼容性,從而提高應用程序的質量和用戶體驗,人話就是更好的操控
。
注釋前面加的默認緩存代碼。
首先在使用ChromiumWebBrowser
控件的后臺代碼里,注冊請求攔截處理程序,CefBrowser
是控件名,CefRequestHandlerc
是處理程序:
public TestCefCacheView() { InitializeComponent(); var handler = new CefRequestHandlerc(); CefBrowser.RequestHandler = handler; }
CefSharp里的IRequestHandler
是一個接口,用于處理瀏覽器發出的請求。它定義了一些方法,可以在請求被發送到服務器之前或之后對請求進行處理。
IRequestHandler
的實現類可以用于以下幾個方面:
攔截請求:可以通過實現OnBeforeBrowse方法來攔截請求,從而控制瀏覽器的行為。例如,可以在請求被發送到服務器之前檢查請求的URL,如果不符合要求,則可以取消請求或者重定向到其他頁面。
修改請求:可以通過實現OnBeforeResourceLoad方法來修改請求,例如可以添加一些自定義的HTTP頭信息,或者修改請求的URL。
處理響應:可以通過實現OnResourceResponse方法來處理服務器返回的響應,例如可以檢查響應的狀態碼和內容,從而決定是否繼續加載頁面。
緩存控制:可以通過實現OnQuotaRequest方法來控制緩存的大小和清除策略,從而優化緩存的使用。
總之,IRequestHandler
的實現類可以用于控制瀏覽器的行為,優化網絡請求和緩存的使用,從而提高應用程序的性能和用戶體驗。
我們不直接實現接口IRequestHandler
,而是繼承它的一個默認實現類RequestHandler
,這可以簡化我們的開發,畢竟實現接口要列出一系列接口方法。
我們重載方法GetResourceRequestHandler
, 在這個方法里返回CefResourceRequestHandler
實例,頁面中資源請求時會調用此方法:
using CefSharp; using CefSharp.Handler; namespace WpfWithCefSharpCacheDemo.Caches; internal class CefRequestHandlerc : RequestHandler { protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling) { // 一個請求用一個CefResourceRequestHandler return new CefResourceRequestHandler(); } }
在CefSharp中,IResourceRequestHandler
接口是用于處理資源請求的,它可以攔截瀏覽器發出的資源請求,例如圖片、CSS、JavaScript等,從而實現對資源請求的控制和優化。
具體來說,IResourceRequestHandler
接口定義了一些方法,例如OnBeforeResourceLoad
、OnResourceResponse
等方法,這些方法可以用于攔截請求、修改請求、處理響應等方面。例如:
OnBeforeResourceLoad:在瀏覽器請求資源之前被調用,可以用于修改請求,例如添加一些自定義的HTTP頭信息,或者修改請求的URL。
OnResourceResponse:在瀏覽器接收到服務器返回的響應之后被調用,可以用于處理響應,例如檢查響應的狀態碼和內容,從而決定是否繼續加載頁面。
OnResourceLoadComplete:在資源加載完成后被調用,可以用于處理資源加載完成后的操作,例如保存資源到本地緩存。
通過實現IResourceRequestHandler
接口,可以對資源請求進行攔截和優化,從而提高應用程序的性能和用戶體驗。
這里我們也不直接實現IResourceRequestHandler
接口,我們定義CefResourceRequestHandler
類,繼承該接口的默認實現類ResourceRequestHandler
。
在下面的CefResourceRequestHandler
類中:
GetResourceHandler
方法:處理資源是否需要緩存,返回null不緩存,返回CefResourceHandler
表示需要緩存,在這個類中做跨域處理。 GetResourceResponseFilter
方法:注冊資源緩存的操作類,即資源下載的實現。 OnBeforeResourceLoad
方法:在這個方法里,我們可以實現給頁面傳遞header參數。
using System.Collections.Specialized; using CefSharp; using CefSharp.Handler; namespace WpfWithCefSharpCacheDemo.Caches; internal class CefResourceRequestHandler : ResourceRequestHandler { private string _localCacheFilePath; private bool IsLocalCacheFileExist => System.IO.File.Exists(_localCacheFilePath); protected override IResourceHandler? GetResourceHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request) { try { _localCacheFilePath = CacheFileHelper.CalculateResourceFileName(request.Url, request.ResourceType); if (string.IsNullOrWhiteSpace(_localCacheFilePath)) { return null; } } catch { return null; } if (!IsLocalCacheFileExist) { return null; } return new CefResourceHandler(_localCacheFilePath); } protected override IResponseFilter? GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) { return IsLocalCacheFileExist ? null : new CefResponseFilter { LocalCacheFilePath = _localCacheFilePath }; } protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) { var headers = new NameValueCollection(request.Headers); headers["Authorization"] = "Bearer xxxxxx.xxxxx.xxx"; request.Headers = headers; return CefReturnValue.Continue; } }
在CefSharp中,IResourceHandler
接口是用于處理資源的,它可以攔截瀏覽器發出的資源請求,并返回自定義的資源內容,從而實現對資源的控制和優化。
具體來說,IResourceHandler
接口定義了一些方法,例如ProcessRequest
、GetResponseHeaders
、ReadResponse
等方法,這些方法可以用于處理資源請求、獲取響應頭信息、讀取響應內容等方面。例如:
ProcessRequest:在瀏覽器請求資源時被調用,可以用于處理資源請求,例如從本地緩存中讀取資源內容,或者從網絡中下載資源內容。
GetResponseHeaders:在瀏覽器請求資源時被調用,可以用于獲取響應頭信息,例如設置響應的MIME類型、緩存策略等。
ReadResponse:在瀏覽器請求資源時被調用,可以用于讀取響應內容,例如從本地緩存中讀取資源內容,或者從網絡中下載資源內容。
通過實現IResourceHandler接口,可以對資源進行自定義處理,例如從本地緩存中讀取資源內容,從而提高應用程序的性能和用戶體驗。
這里我們也不直接實現IResourceHandler
接口,我們定義CefResourceHandler
類,繼承該接口的默認實現類ResourceHandler
。
在CefResourceHandler
的構造函數里只處理跨域問題,其他需求可通過上面接口的方法查找資料處理即可:
using CefSharp; using System.IO; namespace WpfWithCefSharpCacheDemo.Caches; internal class CefResourceHandler : ResourceHandler { public CefResourceHandler(string filePath, string mimeType = null, bool autoDisposeStream = false, string charset = null) : base() { if (string.IsNullOrWhiteSpace(mimeType)) { var fileExtension = Path.GetExtension(filePath); mimeType = Cef.GetMimeType(fileExtension); mimeType = mimeType ?? DefaultMimeType; } var stream = File.OpenRead(filePath); StatusCode = 200; StatusText = "OK"; MimeType = mimeType; Stream = stream; AutoDisposeStream = autoDisposeStream; Charset = charset; Headers.Add("Access-Control-Allow-Origin", "*"); } }
在CefSharp中,IResponseFilter
接口是用于過濾響應內容的,它可以攔截瀏覽器接收到的響應內容,并對其進行修改或者過濾,從而實現對響應內容的控制和優化。
具體來說,IResponseFilter
接口定義了一些方法,例如InitFilter
、Filter
、GetSize
等方法,這些方法可以用于初始化過濾器、過濾響應內容、獲取過濾后的響應內容大小等方面。例如:
InitFilter:在瀏覽器接收到響應內容時被調用,可以用于初始化過濾器,例如設置過濾器的狀態、獲取響應頭信息等。
Filter:在瀏覽器接收到響應內容時被調用,可以用于過濾響應內容,例如修改響應內容、刪除響應內容等。
GetSize:在瀏覽器接收到響應內容時被調用,可以用于獲取過濾后的響應內容大小,例如用于計算響應內容的壓縮比例等。
站長使用的CefSharp.Wpf
的89.0.170.0
版本中的IResponseFilter
接口沒有GetSize
方法。在該版本中,IResponseFilter
接口只定義了兩個方法:InitFilter
和Filter
。
如果在該版本中您需要獲取過濾后的響應內容大小,可以考慮在Filter
方法中自行計算。例如,在Filter
方法中,您可以將過濾后的響應內容寫入一個緩沖區,并記錄緩沖區的大小,最后返回過濾后的響應內容和緩沖區的大小。
public class MyResponseFilter : IResponseFilter { private MemoryStream outputStream = new MemoryStream(); public void Dispose() { outputStream.Dispose(); } public bool InitFilter() { return true; } public FilterStatus Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten) { dataInRead = 0; dataOutWritten = 0; byte[] buffer = new byte[4096]; int bytesRead = 0; do { bytesRead = dataIn.Read(buffer, 0, buffer.Length); if (bytesRead > 0) { outputStream.Write(buffer, 0, bytesRead); } } while (bytesRead > 0); byte[] outputBytes = outputStream.ToArray(); dataOut.Write(outputBytes, 0, outputBytes.Length); dataInRead = outputBytes.Length; dataOutWritten = outputBytes.Length; return FilterStatus.Done; } public int GetResponseFilterBufferSize() { return 0; } public int GetResponseFilterDelay() { return 0; } }
在上述示例代碼中,我們在Filter
方法中將過濾后的響應內容寫入了一個MemoryStream
對象中,并記錄了緩沖區的大小。最后,我們在Filter方法的返回值中返回了過濾后的響應內容和緩沖區的大小。
總結,通過實現IResponseFilter
接口,可以對響應內容進行自定義處理,例如對響應內容進行壓縮、加密等操作,從而提高應用程序的性能和安全性。
本文示例這里定義類CefResponseFilter
直接實現接口處理文件緩存實際操作類,即資源下載實現:
using CefSharp; using System.IO; namespace WpfWithCefSharpCacheDemo.Caches; internal class CefResponseFilter : IResponseFilter { public string LocalCacheFilePath { get; set; } private const int BUFFER_LENGTH = 1024; private bool isFailCacheFile; public FilterStatus Filter(Stream? dataIn, out long dataInRead, Stream? dataOut, out long dataOutWritten) { dataInRead = 0; dataOutWritten = 0; if (dataIn == null) { return FilterStatus.NeedMoreData; } var length = dataIn.Length; var data = new byte[BUFFER_LENGTH]; var count = dataIn.Read(data, 0, BUFFER_LENGTH); dataInRead = count; dataOutWritten = count; dataOut?.Write(data, 0, count); try { CacheFile(data, count); } catch { // ignored } return length == dataIn.Position ? FilterStatus.Done : FilterStatus.NeedMoreData; } public bool InitFilter() { try { var dirPath = Path.GetDirectoryName(LocalCacheFilePath); if (!string.IsNullOrWhiteSpace(dirPath) && !Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } } catch { // ignored } return true; } public void Dispose() { } private void CacheFile(byte[] data, int count) { if (isFailCacheFile) { return; } try { if (!File.Exists(LocalCacheFilePath)) { using var fs = File.Create(LocalCacheFilePath); fs.Write(data, 0, count); } else { using var fs = File.Open(LocalCacheFilePath, FileMode.Append); fs.Write(data,0,count); } } catch { isFailCacheFile = true; File.Delete(LocalCacheFilePath); } } }
緩存文件幫助類,用于管理頁面的ajax接口緩存白名單、緩存文件路徑規范等:
using CefSharp; using System; using System.Collections.Generic; using System.IO; namespace WpfWithCefSharpCacheDemo.Caches; internal static class CacheFileHelper { private const string DEV_TOOLS_SCHEME = "devtools"; private const string DEFAULT_INDEX_FILE = "index.html"; private static HashSet<string> needInterceptedAjaxInterfaces = new(); private static string CachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "caches"); public static void AddInterceptedAjaxInterfaces(string url) { if (needInterceptedAjaxInterfaces.Contains(url)) { return; } needInterceptedAjaxInterfaces.Add(url); } private static bool IsNeedInterceptedAjaxInterface(string url, ResourceType resourceType) { var uri = new Uri(url); if (DEV_TOOLS_SCHEME == url) { return false; } if (ResourceType.Xhr == resourceType && !needInterceptedAjaxInterfaces.Contains(url)) { return false; } return true; } public static string? CalculateResourceFileName(string url, ResourceType resourceType) { if (!IsNeedInterceptedAjaxInterface(url, resourceType)) { return default; } var uri = new Uri(url); var urlPath = uri.LocalPath; if (urlPath.StartsWith("/")) { urlPath = urlPath.Substring(1); } var subFilePath = urlPath; if (ResourceType.MainFrame == resourceType || string.IsNullOrWhiteSpace(urlPath)) { subFilePath = Path.Combine(urlPath, DEFAULT_INDEX_FILE); } var hostCachePath = Path.Combine(CachePath, uri.Host); var fullFilePath = Path.Combine(hostCachePath, subFilePath); return fullFilePath; } }
自定義緩存的子目錄以資源的域名(Host)為目錄名稱創建:
打開緩存的dotnet9.com目錄,通過查看目錄結構和程序發布目錄基本一致,這更適合人看了,是不?
第一點,站長目前遇到的問題,后面4點由Token AI提供解釋。
建議用Route(路由的方式:https://dotnet9.com/albums/wpf)代替QueryString(查詢參數的試工:https://dotnet9.com/albums?slug=wpf)的方式,站長有空再研究下QueryString的緩存方式。
如果確實資源帶QueryString,那對于這種資源就放開緩存,直接通過網絡請求吧。
如果自定義緩存不正確地處理了緩存一致性,可能會導致瀏覽器顯示過期的內容或者不一致的內容。例如,如果緩存了一個網頁,但是該網頁在服務器上已經被更新了,如果自定義緩存沒有正確地處理緩存一致性,可能會導致瀏覽器顯示過期的網頁內容。
如果自定義緩存沒有正確地管理緩存空間,可能會導致瀏覽器占用過多的內存或者磁盤空間。例如,如果自定義緩存緩存了大量的數據,但是沒有及時清理過期的數據或者限制緩存的大小,可能會導致瀏覽器占用過多的內存或者磁盤空間。
如果自定義緩存沒有正確地處理緩存性能,可能會導致瀏覽器的性能下降。例如,如果自定義緩存沒有正確地處理緩存的讀取和寫入,可能會導致瀏覽器的響應速度變慢。
如果自定義緩存沒有正確地處理緩存安全,可能會導致瀏覽器的安全性受到威脅。例如,如果自定義緩存緩存了敏感數據,但是沒有正確地處理緩存的加密和解密,可能會導致敏感數據泄露。
因此,在自定義緩存時,需要注意處理緩存一致性、緩存空間、緩存性能和緩存安全等問題,以確保瀏覽器的正常運行和安全性。
讀到這里,這篇“C#怎么使用CefSharp自定義緩存”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。