首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在CefSharp中使用本地构建的网页

在CefSharp中使用本地构建的网页
EN

Stack Overflow用户
提问于 2015-02-24 13:53:30
回答 4查看 28.1K关注 0票数 16

我在Winform中创建了一个CefSharp浏览器,我需要在内存中动态构建一个CefSharp页面,然后让CefSharp呈现它。

理想情况下,我希望将包含HTML的字符串传递给构造函数,但它需要一个URL。答案可能是否定的,但是否有一个指令可以在字符串前面加上,让CefSharp知道它是一个包含网页的字符串?那么CefSharp会创建一个临时文件吗?

如果没有,Chromium文件夹设置在哪里?如果我把一个文件写到那里,然后把它作为一个完全限定的路径传递,它会起作用吗?我知道Chrome将支持像file:///Users/dmacdonald/Documents/myFile.htm这样的URL,但不确定如何使用临时结构来形成URL。

这是我的新代码,但我的浏览器对象没有ResourceHandler属性。我看到它有一个ResourceHandlerFactory

代码语言:javascript
运行
复制
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);
        }
    }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-09-18 17:22:11

简单的方法(一“文件”,一页)

LoadString()可用于直接从字符串加载:

代码语言:javascript
运行
复制
ChromiumWebBrowser.LoadString(string html, string url);

或者,LoadHtml()可以以给定的编码方式从字符串加载:

代码语言:javascript
运行
复制
ChromiumWebBrowser.LoadHtml(string html, string url, Encoding encoding);

我尝试了这两种方法,它们似乎都能工作,至少在CefSharp.Wpf v51.0.0中是这样的。根据WebBrowserExtensions.cs的说法,LoadHtml()使用RegisterHandler()注册ResourceHandler。我不清楚LoadString()是如何工作的,但这两个函数似乎具有相同的效果。

确保对假URL使用有效的URL格式,如:

代码语言:javascript
运行
复制
https://myfakeurl.com

复杂的方法(多个“文件”,如doc +映像)

  1. 创建一个从IResourceHandlerFactory派生的类。使用VS2015,使用红色下划线的名称应该提供实现接口的选项。这个自动完成选项极大地简化了类的创建,所以一定要使用它。
  2. 类似于步骤1,创建一个从IResourceHandler派生的类。如果可以的话,一定要使用实现界面自动完成选项.
  3. 在步骤1中创建的类(从IResourceHandlerFactory派生)中,有一个名为GetResourceHandler()的函数。在此函数中,从步骤2(基于IResourceHandler)返回派生类的一个新实例。在这里使用new是必要的,因为网络浏览器可以同时请求多个文件。每个IResourceHandler实例都应该处理来自浏览器的一个请求(不用担心,这是为您完成的)。
  4. 正如OP所提到的,浏览器控件有一个名为ResourceHandlerFactory的成员。将此成员设置为您在步骤1(从IResourceHandlerFactory派生)中创建的类的新实例。这就是将Chromium浏览器控件链接到您的接口类的内容。在步骤3中,您将两个类连接在一起,因此我们有一个完整的链。
  5. 在步骤2的类中,有一个名为ProcessRequest()的函数。这是Web页面发出请求时调用的第一个函数。您的目标是记录请求的URL和任何POST数据,然后决定是否允许请求,调用callback.Continue()callback.Cancel()。返回true继续。
  6. 同样,在步骤2中的类中,有一个名为GetResponseHeaders()的函数。这是第二个函数。您的目标是检查URL,可能从存储它的地方(但尚未发送)获取文件数据,确定响应长度(文件或字符串大小),并在响应对象中设置适当的状态代码。确保设置所有这些变量,以便请求能够正确进行。
  7. 在第2步的类中,最后一步是在第三个被调用的函数:ReadResponse()中完成请求。在此函数中,将步骤6中获取的数据写入dataOut流。如果您的数据超过32 in,您可能需要发送多个块。绝对要确保将给定调用中的写入量限制为dataOut流的长度。将bytesRead设置为您在此特定调用中所写的任何内容。在最后一次调用中,当不再保留数据时,只需将bytesRead设置为零并返回false。因为给定文件可能多次被调用,所以一定要跟踪当前的读取位置,以便知道您所在的位置以及发送了多少数据。

对于那些不熟悉此问题的人,您可以将直接编译到EXE中的数据文件存储到项目中,并将其“构建操作”设置为“嵌入式资源”,然后使用System.Reflection.Assembly.GetManifestResourceStream()以编程方式加载数据。使用上述方法,不需要从磁盘创建或读取任何文件。

票数 13
EN

Stack Overflow用户

发布于 2018-04-24 20:14:56

您可能需要使用自定义方案处理程序,以便为本地文件服务,并“绕过”有关文件协议的铬安全性。

我在这件事上写了博客帖子

您要添加的是您的方案处理程序及其工厂:

代码语言:javascript
运行
复制
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之前注册它:

代码语言:javascript
运行
复制
var settings = new CefSettings
{
  BrowserSubprocessPath = GetCefExecutablePath()
};

settings.RegisterScheme(new CefCustomScheme
{
  SchemeName = CustomProtocolSchemeHandlerFactory.SchemeName,
  SchemeHandlerFactory = new CustomProtocolSchemeHandlerFactory()
});
票数 5
EN

Stack Overflow用户

发布于 2015-02-24 16:06:11

有关为内存中字符串注册ResourceHandler的示例,请参见ResourceHandler

正如您所看到的,它仍然有一个URL (web资源通常都有这个URL),但它可能是您的选择之一。

下面是GitHub搜索如何在WinForms (和WPF)示例应用程序中调用它:https://github.com/cefsharp/CefSharp/search?utf8=%E2%9C%93&q=RegisterTestResources

另一个,可能不太有利的选项,有一个临时文件(任何地方?)在本地文件系统中使用FileAccessFromFileUrlsAllowed

从以下评论中更新

您现在使用的是什么CefSharp版本?注如果您查看github.com/CefSharp/CefSharp/ resource并搜索,您将看到版本49中的API更改(查看该版本的最新更改)--请参阅下面的评论,以了解

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28697613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档