CefSharp.Wpf浏览器控件如何使用本地文件资源显示网页
How to display a web page by CefSharp.Wpf browser control with local file resources
我正在尝试使用 CefSharp.Wpf NuGet 包 (v79.1.360) 从磁盘显示一个简单的 html 网页。
页面依赖于本地文件(javascript、css 等...),这些文件位于与页面本身不同的目录中。
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="file:///G:/AngularJS/Framework/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="MyApp.css">
<script src="file:///G:/AngularJS/Framework/angular.min.js"></script>
<script src="file:///G:/AngularJS/Framework/jquery.min.js"></script>
<script src="file:///G:/AngularJS/Framework/bootstrap.min.js"></script>
<script src="MyApp.js"></script>
<title></title>
</head>
<body>
<p class="font-weight-bold">Select address</p>
<table class="table table-hover">
<thead>
<tr class="bg-primary">
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Code</th>
<th scope="col">City</th>
<th scope="col">Street</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="address in Model.AddressList"
ng-click="Model.PickRow(address)"
ng-style="{'background-color': address.Background}">
<td>{{address.Id}}</td>
<td>{{address.Name}}</td>
<td>{{address.PostalCode}}</td>
<td>{{address.City}}</td>
<td>{{address.Street}}</td>
</tr>
</tbody>
</table>
</body>
</html>
我可以在基于 chromium 的 Web 浏览器 (Firefox) 上使用修改后的设置显示该页面:
security.fileuri.strict_origin_policy假
-> Firefox 不是基于 chromium 的网络浏览器,所以我用 google chrome 测试了它,它也能正常工作。
在我的网络研究中,我发现这个 post 与这个问题相关(不幸的是这个 post 来自 2014):
https://github.com/cefsharp/CefSharp/issues/572
所以我尝试为cef sharp控件设置浏览器设置:
<Window x:Class="WebControl.MyWebBrowser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cefSharpCore="clr-namespace:CefSharp;assembly=CefSharp.Core"
xmlns:cefSharpWpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
Height="300" Width="300">
<Grid>
<cefSharpWpf:ChromiumWebBrowser>
<cefSharpWpf:ChromiumWebBrowser.BrowserSettings>
<cefSharpCore:BrowserSettings WebSecurity="Disabled"
FileAccessFromFileUrls="Enabled"
UniversalAccessFromFileUrls="Enabled"/>
</cefSharpWpf:ChromiumWebBrowser.BrowserSettings>
</cefSharpWpf:ChromiumWebBrowser>
</Grid>
</Window>
但这行不通。我也尝试在代码隐藏文件中设置设置,但没有成功。
长话短说:
Current result
Expected result
如果有人有解决办法请告诉我。
提前感谢阅读post:-)
感谢 amaitland 带领我走向正确的方向:
我强烈建议不要在从本地磁盘加载时使用 file:///。适用不同的安全限制,并且有很多限制。我建议使用 Scheme 处理程序或实现您自己的 IResourceRequestHandlerFactory。 (加载数据:编码的 URI 也非常方便,特别是对于 OffScreen 项目)。
如果您选择忽略此建议,您将必须自己解决使用 file:/// 遇到的任何问题。 ceforum 是最好的资源。
复制自:https://github.com/cefsharp/CefSharp/wiki/General-Usage#file-uri-file
解决方案是创建自定义方案处理程序:
https://github.com/cefsharp/CefSharp/wiki/General-Usage#scheme-handler
1) 我将 angular、bootstrap 和 jquery 文件作为资源添加到我的 visual studio 项目中。
2) 我创建了 DiskSchemeHandlerFactory.cs:
public class DiskSchemeHandlerFactory : ISchemeHandlerFactory
{
private static readonly string _SchemeName = "disk";
private static readonly IDictionary<string, string> _ResourceDictionary;
public string SchemeName
{
get { return _SchemeName; }
}
static DiskSchemeHandlerFactory()
{
_ResourceDictionary = new Dictionary<string, string>
{
{ "/angular.min.js", Properties.Resources.angular_min },
{ "/angular.min.js.map", Properties.Resources.angular_min_js },
{ "/bootstrap.min.js", Properties.Resources.bootstrap_min1 },
{ "/bootstrap.min.css", Properties.Resources.bootstrap_min },
{ "/jquery.min.js", Properties.Resources.jquery_min }
};
}
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
//Notes:
// - The 'host' portion is entirely ignored by this scheme handler.
// - If you register a ISchemeHandlerFactory for http/https schemes you should also specify a domain name
// - Avoid doing lots of processing in this method as it will affect performance.
// - Uses the Default ResourceHandler implementation
var uri = new Uri(request.Url);
var fileName = uri.AbsolutePath;
string resource;
if (_ResourceDictionary.TryGetValue(fileName, out resource) && !string.IsNullOrEmpty(resource))
{
var fileExtension = Path.GetExtension(fileName);
return ResourceHandler.FromString(resource, fileExtension);
}
return null;
}
}
3)我修改了MyWebBrowser.xaml.cs的静态构造函数:
static MyWebBrowser()
{
if (Cef.IsInitialized == false)
{
var diskSchemeHandlerFactory = new DiskSchemeHandlerFactory();
var settings = new CefSettings();
settings.RegisterScheme(new CefCustomScheme()
{
SchemeName = diskSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = diskSchemeHandlerFactory
});
Cef.Initialize(settings);
}
}
4) 最后我更改了 html 页面的文件路径:
<script src="disk://angular/angular.min.js"></script>
<script src="disk://jquery/jquery.min.js"></script>
<script src="disk://bootstrap/bootstrap.min.js"></script>
也许我修改它也可以使用完整的文件路径。使用此解决方案,每次我想使用另一个文件时都必须编译我的项目...
我正在尝试使用 CefSharp.Wpf NuGet 包 (v79.1.360) 从磁盘显示一个简单的 html 网页。
页面依赖于本地文件(javascript、css 等...),这些文件位于与页面本身不同的目录中。
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="file:///G:/AngularJS/Framework/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="MyApp.css">
<script src="file:///G:/AngularJS/Framework/angular.min.js"></script>
<script src="file:///G:/AngularJS/Framework/jquery.min.js"></script>
<script src="file:///G:/AngularJS/Framework/bootstrap.min.js"></script>
<script src="MyApp.js"></script>
<title></title>
</head>
<body>
<p class="font-weight-bold">Select address</p>
<table class="table table-hover">
<thead>
<tr class="bg-primary">
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Code</th>
<th scope="col">City</th>
<th scope="col">Street</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="address in Model.AddressList"
ng-click="Model.PickRow(address)"
ng-style="{'background-color': address.Background}">
<td>{{address.Id}}</td>
<td>{{address.Name}}</td>
<td>{{address.PostalCode}}</td>
<td>{{address.City}}</td>
<td>{{address.Street}}</td>
</tr>
</tbody>
</table>
</body>
</html>
我可以在基于 chromium 的 Web 浏览器 (Firefox) 上使用修改后的设置显示该页面: security.fileuri.strict_origin_policy假
-> Firefox 不是基于 chromium 的网络浏览器,所以我用 google chrome 测试了它,它也能正常工作。
在我的网络研究中,我发现这个 post 与这个问题相关(不幸的是这个 post 来自 2014):
https://github.com/cefsharp/CefSharp/issues/572
所以我尝试为cef sharp控件设置浏览器设置:
<Window x:Class="WebControl.MyWebBrowser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cefSharpCore="clr-namespace:CefSharp;assembly=CefSharp.Core"
xmlns:cefSharpWpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
Height="300" Width="300">
<Grid>
<cefSharpWpf:ChromiumWebBrowser>
<cefSharpWpf:ChromiumWebBrowser.BrowserSettings>
<cefSharpCore:BrowserSettings WebSecurity="Disabled"
FileAccessFromFileUrls="Enabled"
UniversalAccessFromFileUrls="Enabled"/>
</cefSharpWpf:ChromiumWebBrowser.BrowserSettings>
</cefSharpWpf:ChromiumWebBrowser>
</Grid>
</Window>
但这行不通。我也尝试在代码隐藏文件中设置设置,但没有成功。
长话短说:
Current result Expected result
如果有人有解决办法请告诉我。
提前感谢阅读post:-)
感谢 amaitland 带领我走向正确的方向:
我强烈建议不要在从本地磁盘加载时使用 file:///。适用不同的安全限制,并且有很多限制。我建议使用 Scheme 处理程序或实现您自己的 IResourceRequestHandlerFactory。 (加载数据:编码的 URI 也非常方便,特别是对于 OffScreen 项目)。 如果您选择忽略此建议,您将必须自己解决使用 file:/// 遇到的任何问题。 ceforum 是最好的资源。
复制自:https://github.com/cefsharp/CefSharp/wiki/General-Usage#file-uri-file
解决方案是创建自定义方案处理程序:
https://github.com/cefsharp/CefSharp/wiki/General-Usage#scheme-handler
1) 我将 angular、bootstrap 和 jquery 文件作为资源添加到我的 visual studio 项目中。
2) 我创建了 DiskSchemeHandlerFactory.cs:
public class DiskSchemeHandlerFactory : ISchemeHandlerFactory
{
private static readonly string _SchemeName = "disk";
private static readonly IDictionary<string, string> _ResourceDictionary;
public string SchemeName
{
get { return _SchemeName; }
}
static DiskSchemeHandlerFactory()
{
_ResourceDictionary = new Dictionary<string, string>
{
{ "/angular.min.js", Properties.Resources.angular_min },
{ "/angular.min.js.map", Properties.Resources.angular_min_js },
{ "/bootstrap.min.js", Properties.Resources.bootstrap_min1 },
{ "/bootstrap.min.css", Properties.Resources.bootstrap_min },
{ "/jquery.min.js", Properties.Resources.jquery_min }
};
}
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
//Notes:
// - The 'host' portion is entirely ignored by this scheme handler.
// - If you register a ISchemeHandlerFactory for http/https schemes you should also specify a domain name
// - Avoid doing lots of processing in this method as it will affect performance.
// - Uses the Default ResourceHandler implementation
var uri = new Uri(request.Url);
var fileName = uri.AbsolutePath;
string resource;
if (_ResourceDictionary.TryGetValue(fileName, out resource) && !string.IsNullOrEmpty(resource))
{
var fileExtension = Path.GetExtension(fileName);
return ResourceHandler.FromString(resource, fileExtension);
}
return null;
}
}
3)我修改了MyWebBrowser.xaml.cs的静态构造函数:
static MyWebBrowser()
{
if (Cef.IsInitialized == false)
{
var diskSchemeHandlerFactory = new DiskSchemeHandlerFactory();
var settings = new CefSettings();
settings.RegisterScheme(new CefCustomScheme()
{
SchemeName = diskSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = diskSchemeHandlerFactory
});
Cef.Initialize(settings);
}
}
4) 最后我更改了 html 页面的文件路径:
<script src="disk://angular/angular.min.js"></script>
<script src="disk://jquery/jquery.min.js"></script>
<script src="disk://bootstrap/bootstrap.min.js"></script>
也许我修改它也可以使用完整的文件路径。使用此解决方案,每次我想使用另一个文件时都必须编译我的项目...