在CefSharp中使用本地构建的网页
我在Winform中创建了一个CefSharp浏览器,我需要在内存中动态构建一个HTML页面,然后让CefSharp渲染它。
理想情况下,我想在构造函数中传递一个包含HTML的字符串,但它需要一个URL。 答案可能是否定的,但是有一个指令可以预先添加字符串让CefSharp知道它是一个包含网页的字符串吗? 那么CefSharp会创建一个临时文件吗?
如果没有,Chromium临时文件夹设置为何处? 如果我将文件写入那里然后将其作为完全限定的路径传递,它会工作吗? 我知道Chrome会支持像file:///Users/dmacdonald/Documents/myFile.htm这样的URL作为URL,但如果使用临时结构则不知道如何形成URL。
这是我的新代码,但我的浏览器对象没有ResourceHandler属性。 我看到它有一个ResourceHandlerFactory
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using CefSharp.WinForms; using CefSharp; namespace DanCefWinForm { public partial class Form1 : Form { public const string TestResourceUrl = "https://maps/resource/load"; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { ChromiumWebBrowser browser = new ChromiumWebBrowser("https://maps/resource/load") { Dock = DockStyle.Fill, }; var handler = browser.ResourceHandler; browser.Location = new Point(20, 20); browser.Size = new Size(100, 100); this.Controls.Add(browser); } } }
简单方法(一个“文件”,一页)
LoadString()可用于直接从字符串加载:
ChromiumWebBrowser.LoadString(string html, string url);
或者, LoadHtml()可以从给定编码中的字符串加载:
ChromiumWebBrowser.LoadHtml(string html, string url, Encoding encoding);
我试过这两个,他们似乎都工作,至少与CefSharp.Wpf v51.0.0 。 根据WebBrowserExtensions.cs , LoadHtml()
使用RegisterHandler()
来注册ResourceHandler
。 我不清楚LoadString()
是如何工作的,但两个函数似乎都有相同的效果。
请务必使用伪URL的有效URL格式,例如:
https://myfakeurl.com
复杂方法(多个“文件”,例如doc + images)
-
创建一个派生自
IResourceHandlerFactory
的类。 使用VS2015,将鼠标hover在带红色下划线的名称上应该提供Implement接口选项。 这个自动完成选项极大地简化了类的创建,因此请务必使用它。 -
与步骤1类似,创建一个派生自
IResourceHandler
的类。 如果可以,请务必使用“ 实施”界面自动完成选项。 -
在步骤1中创建的类(从
IResourceHandlerFactory
派生)中,有一个名为GetResourceHandler()
的函数。 在此函数中,从步骤2返回派生类的新实例(基于IResourceHandler
)。 由于Web浏览器可能同时请求多个文件,因此必须使用new
。 每个IResourceHandler
实例都应该处理来自浏览器的一个请求(不用担心,这是为您完成的)。 -
正如OP所提到的,浏览器控件有一个名为
ResourceHandlerFactory
的成员。 将此成员设置为您在步骤1中创建的类的新实例(从IResourceHandlerFactory
派生)。 这就是将Chromium Web Browser控件链接到接口类的原因。 在第3步中,您链接了两个类,因此我们有一个完整的链。 -
在步骤2的类中,有一个名为
ProcessRequest()
的函数。 这是网页发出请求时调用的第一个函数。 您的目标是记录请求的URL和任何POST数据,然后决定是否允许请求,调用callback.Continue()
或callback.Cancel()
。 返回true继续。 -
同样在第2步的类中,有一个名为
GetResponseHeaders()
的函数。 这是第二个被调用的函数。 您的目标是检查URL,可能从存储它的任何位置获取文件数据(但尚未发送),确定响应长度(文件或字符串大小),并在响应对象中设置适当的状态代码。 请务必设置所有这些变量,以便请求可以正确进行。 -
最后一步,再次在第2步中的类中,是在第三个被调用函数内完成请求:
ReadResponse()
。 在此函数中,将步骤6中提取的数据写入dataOut
流。 如果您的数据超过大约32kB,您可能需要以多个块的forms发送它。 绝对确保将给定调用中写入的数量限制为dataOut
流的长度。 将bytesRead
设置为您在此特定调用中编写的任何内容。 在最后一次调用时,如果没有剩余数据,只需将bytesRead
设置为零并返回false
。 由于您可能会多次调用给定文件,因此请务必跟踪当前的读取位置,以便了解自己的位置以及已发送的数据量。
对于那些不熟悉此事的人,可以将直接编译到EXE中的数据文件存储到项目中并将其“Build Action”设置为“Embedded Resource”,然后使用System.Reflection.Assembly.GetManifestResourceStream()
编程方式加载数据。 System.Reflection.Assembly.GetManifestResourceStream()
。 使用上述方法, 无需从磁盘创建或读取任何文件 。
有关为内存中字符串注册ResourceHandler
的示例,请参阅https://github.com/cefsharp/CefSharp/blob/v39.0.0-pre02/CefSharp.Example/CefExample.cs#L44 。
正如您所看到的,它仍然具有URL(Web资源通常具有该URL),但它可以是您选择的虚拟URL。
以下是GitHub在WinForms(和WPF)示例应用程序中搜索它的方式: https : //github.com/cefsharp/CefSharp/search? utf8 =%E2%9C%93&q = RegisterTestResources
在本地文件系统中使用临时文件(任何地方?)的另一个可能不太有利的选项是使用FileAccessFromFileUrlsAllowed
更新 以下评论:
您现在使用的CefSharp版本是什么? 请注意,如果您查看github.com/cefsharp/CefSharp/releases并搜索resource
您会看到版本49中更改的API(查看该版本的更改) – 请参阅下面的评论以获取更多信息
以下是从文件系统加载资源的自定义工厂的示例:
public class FileResourceHandlerFactory : ISchemeHandlerFactory { private string scheme, host, folder, default_filename; public string Scheme => scheme; public FileResourceHandlerFactory(string scheme, string host, string folder, string default_filename = "index.html") { this.scheme = scheme; this.host = host; this.folder = folder; this.default_filename = default_filename; } private string get_content(Uri uri, out string extension) { var path = uri.LocalPath.Substring(1); path = string.IsNullOrWhiteSpace(path) ? this.default_filename : path; extension = Path.GetExtension(path); return File.ReadAllText(Path.Combine(this.folder, path)); } IResourceHandler ISchemeHandlerFactory.Create(IBrowser browser, IFrame frame, string schemeName, IRequest request) { var uri = new Uri(request.Url); return ResourceHandler.FromString(get_content(uri, out var extension), extension); } }
以下是您将如何应用它:
var settings = new CefSettings(); settings.RegisterScheme(new CefCustomScheme { SchemeName = "app", SchemeHandlerFactory = fileResourceHandlerFactory, IsSecure = true //treated with the same security rules as those applied to "https" URLs }); var chromeBrowser = new ChromiumWebBrowser(); chromeBrowser.Load("app://local");
您可能需要使用自定义方案处理程序,以便提供本地文件,并“绕过”有关文件协议的铬安全性。
我写了关于此事的博客文章 。
你想要添加的是你的方案处理程序及其工厂:
using System; using System.IO; using CefSharp; namespace MyProject.CustomProtocol { public class CustomProtocolSchemeHandler : ResourceHandler { // Specifies where you bundled app resides. // Basically path to your index.html private string frontendFolderPath; public CustomProtocolSchemeHandler() { frontendFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./bundle/"); } // Process request and craft response. public override bool ProcessRequestAsync(IRequest request, ICallback callback) { var uri = new Uri(request.Url); var fileName = uri.AbsolutePath; var requestedFilePath = frontendFolderPath + fileName; if (File.Exists(requestedFilePath)) { byte[] bytes = File.ReadAllBytes(requestedFilePath); Stream = new MemoryStream(bytes); var fileExtension = Path.GetExtension(fileName); MimeType = GetMimeType(fileExtension); callback.Continue(); return true; } callback.Dispose(); return false; } } public class CustomProtocolSchemeHandlerFactory : ISchemeHandlerFactory { public const string SchemeName = "customFileProtocol"; public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request) { return new CustomProtocolSchemeHandler(); } } }
然后在调用 Cef.Initialize 之前注册它:
上述就是C#学习教程:在CefSharp中使用本地构建的网页分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
var settings = new CefSettings { BrowserSubprocessPath = GetCefExecutablePath() }; settings.RegisterScheme(new CefCustomScheme { SchemeName = CustomProtocolSchemeHandlerFactory.SchemeName, SchemeHandlerFactory = new CustomProtocolSchemeHandlerFactory() });
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/950926.html