CefSharp 访问嵌入的前端目录:Scheme 自定义 + 文件夹作为嵌入的资源

CefSharp 是一个开源项目,它为 .NET 提供了嵌入式的 Chromium (CEF),如果你想用前端技术做界面,后端采用 C# 编写,那 CefSharp 是不错的选择。

本文将讲述:CefSharp 自定义属于自己的 Scheme,将前端资源目录下的所有文件全部嵌入 .NET APP 中(即嵌入到 .exe 文件中),并且做到 已嵌入资源 可通过 URL 直接访问

URL Scheme 是什么?

对于 URL 我们都很熟悉,例如 https://www.google.com 就是一个 URL,我们也叫它链接或网址。

可以简单理解:Schemes 表示的是 URL 中的一个位置,Schemes 是 :// 之前的那段字符。

举个栗子 https://www.google.com 这个 URL 的 Schemes 是 https

又例如 file:///C:/Users/qwqcode/Desktop,它的 Schemes 是 file

参见维基百科:List_of_URI_schemes / Uniform_Resource_Identifier

URL 和 URI 的关系:

URL是URI的一种,不仅标识了 Web 资源,还指定了操作或者获取方式,同时指出了主要访问机制和网络位置。

1. 嵌入前端资源目录下的所有文件

假如有一个解决方案,待嵌入的 前端目录 相对于 这个解决方案 的路径是 ..\Frontend\dist ,那么则在这个解决方案的 .csproj 文件中加入:

1
2
3
<EmbeddedResource Include="..\Frontend\dist\**\*.*">
<Link>html_res\%(RecursiveDir)%(Filename)%(Extension)</Link>
</EmbeddedResource>

实例:/Nacollector/Nacollector.csproj#L163

之后,你会发现在该解决方案的文件树列表中,出现了 html_res 文件夹,里面会包含所有前端文件,且已成为嵌入的资源

值得注意的是:解决方案中的目录名只能为小写字母,如 html_res,不能大写。

2. SchemeHandler

接下来,开始写 SchemeHandler 类

SchemeHandler 用于处理用户对指定 Scheme 的请求,并返回响应数据

ResourceSchemeHandler.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using CefSharp;
using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;

public class ResourceSchemeHandler : ResourceHandler
{
public override bool ProcessRequestAsync(IRequest request, ICallback callback)
{
var names = this.GetType().Assembly.GetManifestResourceNames();

Console.WriteLine(names);

Uri u = new Uri(request.Url);
String file = u.Authority + u.AbsolutePath; // 注:目录名需全为小写字母,否则将无法得到 Resource

Assembly ass = Assembly.GetExecutingAssembly();
String resourcePath = ass.GetName().Name + "." + file.Replace("/", "."); // 你可以设置断点看看这里的值

Task.Run(() =>
{
using (callback)
{
if (ass.GetManifestResourceInfo(resourcePath) != null)
{
Stream stream = ass.GetManifestResourceStream(resourcePath);
string mimeType = "application/octet-stream";
switch (Path.GetExtension(file))
{
case ".html":
mimeType = "text/html";
break;
case ".js":
mimeType = "text/javascript";
break;
case ".css":
mimeType = "text/css";
break;
case ".png":
mimeType = "image/png";
break;
case ".appcache":
break;
case ".manifest":
mimeType = "text/cache-manifest";
break;
}

// Reset the stream position to 0 so the stream can be copied into the underlying unmanaged buffer
stream.Position = 0;
// Populate the response values - No longer need to implement GetResponseHeaders (unless you need to perform a redirect)
ResponseLength = stream.Length;
MimeType = mimeType;
StatusCode = (int)HttpStatusCode.OK;
Stream = stream;

callback.Continue();
}
else
{
callback.Cancel();
}
}
});

return true;
}
}

3. SchemeHandlerFactory

最后一步,写 SchemeHandlerFactory

SchemeHandlerFactory 用于负责 实例化 相应的 SchemeHandler,并向外界提供 SchemeName。

ResourceSchemeHandlerFactory.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;

class ResourceSchemeHandlerFactory : ISchemeHandlerFactory
{
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
return new ResourceSchemeHandler();
}

public static string SchemeName {
get {
return "nacollector"; // 这里我设置的 SchemeName 为 nacollector,当然你也可以改成其他的
}
}
}

4. 注册 Scheme

需在调用 Cef.Initialize 前添加 settings.RegisterScheme 进行对 Scheme 的注册,如下:

1
2
3
4
5
6
7
8
9
10
11
var settings = new CefSettings();
// ...

settings.RegisterScheme(new CefCustomScheme()
{
SchemeName = ResourceSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new ResourceSchemeHandlerFactory()
});

// ...
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

5. 完成

到这一步,你就可以访问 nacollector://html_res/index.html

1
var browser = new ChromiumWebBrowser("nacollector://html_res/index.html");
本站文章除注明转载外均为原创,未经允许不要转载哇. ヾ(゚ー゚ヾ) http://qwqaq.com/ee43a4af.html
分享到