use*_*051 11 c# chromium-embedded cefsharp
我在Winform中创建了一个CefSharp浏览器,我需要在内存中动态构建一个HTML页面,然后让CefSharp渲染它.
理想情况下,我想在构造函数中传递一个包含HTML的字符串,但它需要一个URL.答案可能是否定的,但是有一个指令可以预先添加字符串让CefSharp知道它是一个包含网页的字符串吗?然后CefSharp会创建一个临时文件?
如果没有,Chromium临时文件夹设置为何处?如果我将文件写入那里然后将其作为完全限定的路径传递,它会工作吗?我知道Chrome会支持像file:///Users/dmacdonald/Documents/myFile.htm这样的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 = "http://maps/resource/load";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ChromiumWebBrowser browser = new ChromiumWebBrowser("http://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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ael 12
LoadString()可用于直接从字符串加载:
ChromiumWebBrowser.LoadString(string html, string url);
Run Code Online (Sandbox Code Playgroud)
或者,LoadHtml()可以从给定编码中的字符串加载:
ChromiumWebBrowser.LoadHtml(string html, string url, Encoding encoding);
Run Code Online (Sandbox Code Playgroud)
我试过这两个,他们似乎都工作,至少与CefSharp.Wpf v51.0.0.根据WebBrowserExtensions.cs,LoadHtml()用于RegisterHandler()注册ResourceHandler.我不清楚它是如何LoadString()工作的,但两种功能似乎都有相同的效果.
请务必使用伪URL的有效URL格式,例如:
https://myfakeurl.com
Run Code Online (Sandbox Code Playgroud)
创建一个派生自的类IResourceHandlerFactory.使用VS2015,将鼠标悬停在带红色下划线的名称上应该提供Implement接口选项.这个自动完成选项极大地简化了类的创建,因此请务必使用它.
与步骤1类似,创建一个派生类IResourceHandler.如果可以,请务必使用" 实施"界面自动完成选项.
在步骤1中创建的类(派生自IResourceHandlerFactory)中,有一个名为的函数GetResourceHandler().在此函数中,从步骤2返回派生类的新实例(基于IResourceHandler).new由于Web浏览器可能同时请求多个文件,因此在此处使用至关重要 每个IResourceHandler实例都应该处理来自浏览器的一个请求(不用担心,这是为您完成的).
如OP所述,浏览器控件有一个名为的成员ResourceHandlerFactory.将此成员设置为您在步骤1中创建的类的新实例(派生自).这就是将Chromium Web Browser控件链接到接口类的原因.在第3步中,您链接了两个类,因此我们有一个完整的链.IResourceHandlerFactory
在步骤2的类中,有一个名为的函数ProcessRequest().这是网页发出请求时调用的第一个函数.您的目标是记录请求的URL和任何POST数据,然后决定是否允许请求,调用callback.Continue()或callback.Cancel().返回true继续.
再次在第2步的类中,有一个名为的函数GetResponseHeaders().这是第二个被调用的函数.您的目标是检查URL,可能从存储它的任何位置获取文件数据(但尚未发送),确定响应长度(文件或字符串大小),并在响应对象中设置适当的状态代码.请务必设置所有这些变量,以便请求可以正确进行.
最后一步,再次在第2步中的类中,是在第三个被调用函数内完成请求:ReadResponse().在此函数中,将在步骤6中提取的数据写入dataOut流.如果您的数据超过大约32kB,您可能需要以多个块的形式发送它.绝对确保将给定调用中写入的数量限制为dataOut流的长度.设置bytesRead为您在此特定电话中写的任何内容.在最后一次调用时,如果没有剩余数据,只需设置bytesRead为零并返回false.由于给定文件可能会多次调用,因此请务必跟踪当前的读取位置,以便了解自己的位置以及已发送的数据量.
对于那些不熟悉此事的人,可以将直接编译到EXE中的数据文件存储到项目中,并将"Build Action"设置为"Embedded Resource",然后使用编程方式加载数据System.Reflection.Assembly.GetManifestResourceStream().使用上述方法,无需从磁盘创建或读取任何文件.
您可能需要使用自定义方案处理程序,以便为本地文件提供服务,并“绕过”有关文件协议的 chromium 安全性。
我就此事写了博客文章。
您要添加的是您的方案处理程序及其工厂:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在调用Cef.Initialize之前注册它:
var settings = new CefSettings
{
BrowserSubprocessPath = GetCefExecutablePath()
};
settings.RegisterScheme(new CefCustomScheme
{
SchemeName = CustomProtocolSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new CustomProtocolSchemeHandlerFactory()
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16063 次 |
| 最近记录: |