在 Blazor Hybrid 应用中,Razor 组件在设备上本机运行。 组件通过本地互操作通道呈现到嵌入式 Web View 控件。 组件不在浏览器中运行,并且不涉及 WebAssembly。 Razor 组件可快速加载和执行代码,组件可通过 .NET 平台完全访问设备的本机功能。 Web View 中呈现的组件样式与平台相关,可能需要你使用自定义样式表来说明不同平台之间的呈现差异。
如何在Blazor Hybrid中读取本地图片展示?
在Blazor Hybrid经常遇到一些读取选中的图片并且渲染,但是文件的目录在Blazor中直接src填写是无法读取到的,这个时候就可能需要将文件Copy到wwwroot中,或者将其转换Base64放入到html中,但是base64转换图片是很长的一串字符串,这样可能会导致渲染可能卡扽,所以我们将使用js提供的功能去实现,其实在Blazor Hybrid为了兼容,可以采用js提供的部分功能实现,效果更好,
创建一个Winform项目
示图:

添加 Microsoft.AspNetCore.Components.WebView.WindowsFormsNuGet包
dotnet add package Microsoft.AspNetCore.Components.WebView.WindowsForms
修改项目文件的属性
打开BlazorHybrid.csproj项目文件,将Microsoft.NET.Sdk 修改成Microsoft.NET.Sdk.Razor
<Project Sdk="Microsoft.NET.Sdk.Razor">
创建 _Imports.razor文件,添加以下代码
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Routing
创建wwwroot文件夹
创建wwwroot/index.html文件,添加以下代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>WinFormsBlazor</title> <base href="/" /> <link href="css/app.css" rel="stylesheet" /> <link href="WinFormsBlazor.styles.css" rel="stylesheet" /> </head> <body> <div id="app">加载中...</div> <div id="blazor-error-ui"> An unhandled error has occurred. <a href="" class="reload">Reload</a> <a class="dismiss">🗙</a> </div> <!--引用blazor.webview.js Server和web assembly,hybrid的js都不一样--> <script src="_framework/blazor.webview.js"></script> </body> </html>
创建wwwroot/css/app.css添加以下代码
html, body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; } h1:focus { outline: none; } a, .btn-link { color: #0071c1; } .btn-primary { color: #fff; background-color: #1b6ec2; border-color: #1861ac; } .valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; } .invalid { outline: 1px solid red; } .validation-message { color: red; } #blazor-error-ui { background: lightyellow; bottom: 0; box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); display: none; left: 0; padding: 0.6rem 1.25rem 0.7rem 1.25rem; position: fixed; width: 100%; z-index: 1000; } #blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; }
创建Shared/App.razor添加以下代码
<Router AppAssembly="@typeof(MainLayout).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router>
创建Shared/MainLayout.razor添加以下代码
@inherits LayoutComponentBase <div> @Body </div>
选择Form1.cs打开设计窗口,将BlazorWebView拖到Form1中,并且将BlazorWebView的属性中的Dock修改成Fill

将以下命名空间添加到Form1.cs文件的顶部
using Microsoft.AspNetCore.Components.WebView.WindowsForms; using Microsoft.Extensions.DependencyInjection;
在 Form1 构造函数中的 InitializeComponent 方法调用后面,添加以下代码:
var services = new ServiceCollection(); services.AddWindowsFormsBlazorWebView(); blazorWebView1.HostPage = "wwwroot\index.html"; blazorWebView1.Services = services.BuildServiceProvider(); blazorWebView1.RootComponents.Add<App>("#app");
效果如图

修改wwwroot/index.html代码。添加js方法,将以下代码添加到body里面
<script> /** 将byte转url对象 */ function byteToUrl(blob) { // 适配webview和web var myBlob = new Blob([blob], { type: "image/png" }); return (window.URL || window.webkitURL || window || {}).createObjectURL(myBlob); } /** * 释放url对象,因为createObjectURL创建的对象一直会存在可能会占用过多的内存,请注意释放 */ function revokeUrl(url) { (window.URL || window.webkitURL || window || {}).revokeObjectURL(url); } </script>
创建Pages/Index.razor文件,并添加以下代码
@using Microsoft.JSInterop; @inject IJSRuntime JSRuntime @page "/" @if (!string.IsNullOrEmpty(Img)){ <img src="@Img" /> } <input @bind="ImgPath" /> <button @onclick="OnLoad">加载图片</button> <button @onclick="Revoke">释放图片</button> @code { public string? ImgPath { get; set; } private string? Img; private async Task OnLoad() { // 加载目录中的图片获取到byte 通过byteToUrl转换URL对象 可以直接通过url获取到图片 它存在与本地 var file = await File.ReadAllBytesAsync(ImgPath); Img = await JSRuntime.InvokeAsync<string>("byteToUrl", file); } private async Task Revoke() { if (!string.IsNullOrEmpty(Img)){ await JSRuntime.InvokeVoidAsync("revokeUrl", Img); Img = string.Empty; } } } <style> button { background-color: cornflowerblue; height: 30px; font-size: 15px; width: auto; } img{ height:auto; width:auto; } </style>
最终效果:

结尾
我们可以通过createObjectURL加载本地文件或者图片,并且渲染,这样对比copy到wwwroot或者转换base64的效果更好,而且更容易管理,实现也超级容易,用于跨平台实现也算是最佳实现了,
Blazor技术交流:452761192
来自token的分享