新建FilterData类
public class FilterData : IDisposable { private static ConcurrentDictionary<ulong, MemoryStreamResponseFilter> dataFilters = new(); /// <summary> /// 释放标记 /// </summary> private bool disposed; //private ulong Identifier { get; set; } //private MemoryStreamResponseFilter memory { get; set; } public void AddFilter(ulong Identifier, MemoryStreamResponseFilter memory) { dataFilters.TryAdd(Identifier, memory); } public string GetFilter(ulong Identifier) { dataFilters.TryGetValue(Identifier, out MemoryStreamResponseFilter memory); var data = memory?.DataStr; memory?.Close(); dataFilters.TryRemove(Identifier, out MemoryStreamResponseFilter m); return data; } public void Close(ulong Identifier) { dataFilters.TryGetValue(Identifier, out MemoryStreamResponseFilter memory); memory?.Close(); dataFilters.TryRemove(Identifier, out MemoryStreamResponseFilter m); Dispose(); } /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary> public void Dispose() { //必须为true Dispose(true); //通知垃圾回收器不再调用终结器 GC.SuppressFinalize(this); } /// <summary> /// 非密封类可重写的Dispose方法,方便子类继承时可重写 /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { if (disposed) { return; } //清理托管资源 if (disposing) { dataFilters.Clear(); } //告诉自己已经被释放 disposed = true; } ///// <summary> ///// 为了防止忘记显式的调用Dispose方法 ///// </summary> //~FilterData() //{ // //必须为false // Dispose(false); //} }
CustomResourceRequestHandler
/// <summary> /// 返回值拦截 /// </summary> public class CustomResourceRequestHandler : ResourceRequestHandler { private MemoryStream memoryStream; public event EventHandler<OnResourceLoadCompleteEventArgs> OnResourceLoadCompleteEvent; public event EventHandler<OnBeforeResourceLoadEventArgs> OnBeforeResourceLoadEvent; bool Disposed = false; /// <summary> /// 是否过滤,如果不过滤就截获 /// </summary> bool filter = false; /// <summary> /// 过滤、截获 url 列表 和 捕获过滤数据 /// </summary> FilterData filterData { get; set; } public CustomResourceRequestHandler(FilterData Filter, bool _filter) { filterData = Filter; filter = _filter; } protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) { Uri url; if (Uri.TryCreate(request.Url, UriKind.Absolute, out url) == false) { //If we're unable to parse the Uri then cancel the request // avoid throwing any exceptions here as we're being called by unmanaged code return CefReturnValue.Cancel; } if (!filter) { OnBeforeResourceLoadEvent?.Invoke(this,new OnBeforeResourceLoadEventArgs(chromiumWebBrowser, browser, frame, request, callback)); } //NOTE: When executing the callback in an async fashion need to check to see if it's disposed //if (!callback.IsDisposed) //{ // using (callback) // { // if (request.Method == "POST") // { // using (var postData = request.PostData) // { // if (postData != null) // { // var elements = postData.Elements; // var charSet = request.GetCharSet(); // foreach (var element in elements) // { // if (element.Type == PostDataElementType.Bytes) // { // var body = element.GetBody(charSet); // } // } // } // } // } // } //} return base.OnBeforeResourceLoad(chromiumWebBrowser, browser, frame, request, callback); //return CefReturnValue.Continue; } protected override IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) { if (filter) return null; var fil = new MemoryStreamResponseFilter(filter); filterData.AddFilter(request.Identifier, fil); return fil; } protected override void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) { var repData = filterData?.GetFilter(request.Identifier); filterData?.Close(request.Identifier); Debug.WriteLine($"数据输出:-----{repData}"); OnResourceLoadCompleteEvent?.Invoke(this,new OnResourceLoadCompleteEventArgs(chromiumWebBrowser, browser, frame, request, response, status, receivedContentLength, repData)); } protected override void Dispose() { if (Disposed) return; Disposed = true; } }
MemoryStreamResponseFilter
public class MemoryStreamResponseFilter : IResponseFilter { public MemoryStreamResponseFilter(bool _filter) { filter = _filter; } bool Disposed = false; /// <summary> /// 是否过滤,如果不过滤就截获 /// </summary> bool filter = false; private MemoryStream memoryStream; public void Dispose() { //memoryStream?.Dispose(); //memoryStream = null; ////必须为true //Dispose(true); ////通知垃圾回收器不再调用终结器 //GC.SuppressFinalize(this); } protected virtual void Dispose(bool r) { if (Disposed) return; if (r) { memoryStream?.Close(); memoryStream?.Dispose(); memoryStream = null; } Disposed = true; } public void Close() { Dispose(true); } FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten) { try { if (dataIn == null) { dataInRead = 0; dataOutWritten = 0; return FilterStatus.Done; } dataOutWritten = Math.Min(dataIn.Length, dataOut.Length); dataInRead = dataOutWritten; byte[] readBytes = new byte[dataOutWritten]; dataIn.Read(readBytes, 0, (int)dataOutWritten); dataOut.Write(readBytes, 0, (int)dataOutWritten); //copy data to filter memory stream memoryStream.Write(readBytes, 0, (int)dataOutWritten); return dataOutWritten < dataIn.Length ? FilterStatus.NeedMoreData : FilterStatus.Done; } catch (Exception e) { Logger.Default.Error($"IResponseFilter处理出错:{e.Message}"); dataInRead = dataIn.Length; dataOutWritten = dataIn.Length; return FilterStatus.Done; } } bool IResponseFilter.InitFilter() { memoryStream = new MemoryStream(); return true; } public byte[] Data { get { var data = memoryStream.ToArray(); memoryStream?.Close(); memoryStream?.Dispose(); return data; } } public string DataStr { get { var data = Encoding.UTF8.GetString(memoryStream.ToArray()); memoryStream?.Close(); memoryStream?.Dispose(); return data; } } //~MemoryStreamResponseFilter() //{ // //必须false // Dispose(false); //} }
这里会汲级内存无法扩容参考:https://github.com/cefsharp/CefSharp/issues/2433
新建RequestEventHandler类并在此类中调用CustomResourceRequestHandler
public class RequestEventHandler : RequestHandler { public event EventHandler<OnBeforeBrowseEventArgs> OnBeforeBrowseEvent; public event EventHandler<OnOpenUrlFromTabEventArgs> OnOpenUrlFromTabEvent; public event EventHandler<OnCertificateErrorEventArgs> OnCertificateErrorEvent; public event EventHandler<OnPluginCrashedEventArgs> OnPluginCrashedEvent; public event EventHandler<GetAuthCredentialsEventArgs> GetAuthCredentialsEvent; public event EventHandler<OnRenderProcessTerminatedEventArgs> OnRenderProcessTerminatedEvent; public event EventHandler<OnQuotaRequestEventArgs> OnQuotaRequestEvent; public event EventHandler<System.EventArgs> requestEvent; public event EventHandler<System.EventArgs> UpdateRequestEvent; public bool Isintercept { get; set; } = false; protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect) { var args = new OnBeforeBrowseEventArgs(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect); OnBeforeBrowseEvent?.Invoke(this, args); return args.CancelNavigation; } protected override bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) { var args = new OnOpenUrlFromTabEventArgs(chromiumWebBrowser, browser, frame, targetUrl, targetDisposition, userGesture); OnOpenUrlFromTabEvent?.Invoke(this, args); return args.CancelNavigation; } protected override bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) { var args = new OnCertificateErrorEventArgs(chromiumWebBrowser, browser, errorCode, requestUrl, sslInfo, callback); OnCertificateErrorEvent?.Invoke(this, args); EnsureCallbackDisposal(callback); return args.ContinueAsync; } protected override void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath) { var args = new OnPluginCrashedEventArgs(chromiumWebBrowser, browser, pluginPath); OnPluginCrashedEvent?.Invoke(this, args); } protected override bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback) { var args = new GetAuthCredentialsEventArgs(chromiumWebBrowser, browser, originUrl, isProxy, host, port, realm, scheme, callback); GetAuthCredentialsEvent?.Invoke(this, args); EnsureCallbackDisposal(callback); return args.ContinueAsync; } /// <summary> /// 线程终止 /// </summary> /// <param name="chromiumWebBrowser"></param> /// <param name="browser"></param> /// <param name="status"></param> protected override void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status) { var args = new OnRenderProcessTerminatedEventArgs(chromiumWebBrowser, browser, status); OnRenderProcessTerminatedEvent?.Invoke(this, args); } protected override bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) { var args = new OnQuotaRequestEventArgs(chromiumWebBrowser, browser, originUrl, newSize, callback); OnQuotaRequestEvent?.Invoke(this, args); EnsureCallbackDisposal(callback); return args.ContinueAsync; } /// <summary> /// 拦截请求 /// </summary> /// <param name="chromiumWebBrowser"></param> /// <param name="browser"></param> /// <param name="frame"></param> /// <param name="request"></param> /// <param name="isNavigation"></param> /// <param name="isDownload"></param> /// <param name="requestInitiator"></param> /// <param name="disableDefaultHandling"></param> /// <returns></returns> protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling) { if (Isintercept) { //requestEvent?.Invoke(request, new System.EventArgs()); var resource = new CustomResourceRequestHandler(new FilterData(), false); resource.OnBeforeResourceLoadEvent += (e, args) => { UpdateRequestEvent?.Invoke(this, args); }; resource.OnResourceLoadCompleteEvent += (e, args) => { requestEvent?.Invoke(this, args); }; return resource; } return base.GetResourceRequestHandler( chromiumWebBrowser, browser, frame, request, isNavigation, isDownload, requestInitiator, ref disableDefaultHandling); // 先调用基类的实现,断点调试 } private static void EnsureCallbackDisposal(IRequestCallback callbackToDispose) { if (callbackToDispose != null && !callbackToDispose.IsDisposed) { callbackToDispose.Dispose(); } } private static void EnsureCallbackDisposal(IAuthCallback callbackToDispose) { if (callbackToDispose != null && !callbackToDispose.IsDisposed) { callbackToDispose.Dispose(); } } }
使用:
_customRequestHandler = new RequestEventHandler(); chromeBrowser.RequestHandler = _customRequestHandler;
评论区