在。net MAUI Blazor中,我可以使用img标记来显示来自wwwroot文件夹的图像。但是如何显示来自设备内部存储的图像呢?以及如何从应用程序资源显示图像?
From Internal storage
我们可以读入bytes
并将其转换为base64
字符串,然后显示在img
标签上。
在FileSystem.CacheDirectory
文件夹中放置了一个名为dog.png
的图像
@if (imageSource is not null)
{
<div>
<img src="@imageSource" width="200" height="200" />
</div>
}
@code {
private string? imageSource;
protected override void OnInitialized()
{
var newFile = Path.Combine(FileSystem.CacheDirectory, "dog.png");
var imageBytes = File.ReadAllBytes(newFile);
imageSource = Convert.ToBase64String(imageBytes);
imageSource = string.Format("data:image/png;base64,{0}", imageSource);
}
}
@if (imageSource is not null)
{
<div>
<img src="@imageSource" width="200" height="200" />
</div>
}
@code {
private string? imageSource;
protected override void OnInitialized()
{
var newFile = Path.Combine(FileSystem.CacheDirectory, "dog.png");
var imageBytes = File.ReadAllBytes(newFile);
imageSource = Convert.ToBase64String(imageBytes);
imageSource = string.Format("data:image/png;base64,{0}", imageSource);
}
}
根据我的研究:实际上,您可以使用:AppDomain.CurrentDomain.BaseDirectory
获取razor应用程序中wwwroot文件夹的路径。在windows中,您可以在此文件夹中添加可从Blazor HTML访问的文件。然而,在Android中,wwwroot文件夹嵌入在应用程序中,将无法访问(AppDomain.CurrentDomain.BaseDirectory
返回一个空文件夹)。
在BlazorWebView
类中查看。net MAUI github repo后,我发现:
public virtual IFileProvider CreateFileProvider(string contentRootDir)
{
// Call into the platform-specific code to get that platform's asset file provider
return ((BlazorWebViewHandler)(Handler!)).CreateFileProvider(contentRootDir);
}
可用于将文件传递给Blazor。例如,如果您希望访问AppDataDirectory中的所有文件:
using Microsoft.AspNetCore.Components.WebView.Maui;
using Microsoft.Extensions.FileProviders;
public class CustomFilesBlazorWebView : BlazorWebView
{
public override IFileProvider CreateFileProvider(string contentRootDir)
{
var lPhysicalFiles = new PhysicalFileProvider(FileSystem.Current.AppDataDirectory);
return new CompositeFileProvider(lPhysicalFiles, base.CreateFileProvider(contentRootDir));
}
}
Then inMainPage.xaml
:
<local:CustomFilesBlazorWebView HostPage="wwwroot/index.html" x:Name="WebView">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</local:CustomFilesBlazorWebView>
例如,如果在AppDataDirectory中,您在任何Blazor组件中都有一个文件images/user.png
,您可以使用:
<img src="images/user.png" />
要显示from resource,请参见:Blazor Hybrid static Files/.Net Maui:
- 将文件添加到项目中,在名为Resources/Raw的文件夹中。
- 确保file/Properties/Build Action = MauiAsset.
- 创建一个razor组件
-
- 调用
Microsoft.Maui.Storage.FileSystem.OpenAppPackageFileAsync
获取资源的流。
- 调用
-
- 使用StreamReader读取流。
-
- 调用StreamReader。ReadToEndAsync读取文件
示例剃刀代码(来自该链接):
@page "/static-asset-example"
@using System.IO
@using Microsoft.Extensions.Logging
@using Microsoft.Maui.Storage
@inject ILogger<StaticAssetExample> Logger
<h1>Static Asset Example</h1>
<p>@dataResourceText</p>
@code {
public string dataResourceText = "Loading resource ...";
protected override async Task OnInitializedAsync()
{
try
{
using var stream =
await FileSystem.OpenAppPackageFileAsync("Data.txt");
using var reader = new StreamReader(stream);
dataResourceText = await reader.ReadToEndAsync();
}
catch (FileNotFoundException ex)
{
dataResourceText = "Data file not found.";
Logger.LogError(ex, "'Resource/Raw/Data.txt' not found.");
}
}
}
要从razor代码访问本地文件(不是资源中的资产),您需要一个service
,它给出文件名(或相对路径),以流的形式返回文件内容。
我没有找到一个文档告诉如何为毛伊岛做这个,然后把它注入剃刀代码。
这样的服务将使用。net文件系统助手来访问文件。这将类似于上面的MauiAsset示例,但使用路径帮助器之一,而不是调用OpenAppPackageFileAsync。
TBD -有人给参考链接或例子?
我就这样解决了。
- 将png图像添加到ResourcesRaw中,并设置为MauiAsset编译类型
- 检查项目文件,避免通过ItemGroup->没有删除。在这种情况下,删除与图像相关的ItemGroup。 :后
在我的razor组件中HTML
<img src="@imageSource">
代码部分:
private string? imageSource;
protected override async Task OnInitializedAsync()
{
try
{
using var stream =
await FileSystem.OpenAppPackageFileAsync("testimage.png");
using var reader = new StreamReader(stream);
byte[] result;
using (var streamReader = new MemoryStream())
{
stream.CopyTo(streamReader);
result = streamReader.ToArray();
}
imageSource = Convert.ToBase64String(result);
imageSource = string.Format("data:image/png;base64,{0}", imageSource);
}
catch (Exception ex)
{
//log error
}
}