MAUI桌面应用中如何让wwwroot内新生成的图片即时显示?
MAUI/Razor桌面应用图片生成后无法即时显示的解决办法
问题描述
我有一个面向桌面应用的MAUI/Razor项目,点击「Create Chart」按钮后,会在wwwroot/chart/目录下生成新的图片,但该图片无法在应用中即时显示,只有重启应用后才会出现。如何让图片在生成后立即显示?是否需要重载wwwroot?
现有代码
Razor页面代码
@page "/notfallberechnung" <div class="row"> <div class="row"> <div class="col-5"> <button @onclick="CreateChartAsync">Create Chart</button> </div> </div> <br /> <br /> <div class="row"> <div class="col-5"> <ImageViewer Url="@currentChartPath" FitMode="ObjectFitMode.Fill" /> </div> </div> </div>
C#后台代码
using BootstrapBlazor.Components; using Microsoft.AspNetCore.Components; using System.Drawing; namespace Expo.Pages { public partial class Notfallberechnung : ComponentBase { private string currentChartPath = "./chart/Mode-5000.bmp"; public async void CreateChartAsync() { var n = new Bitmap(314, 314); using (var g = Graphics.FromImage(n)) { g.DrawString("hallo test", new System.Drawing.Font("Tahoma", 8), new SolidBrush(System.Drawing.Color.Red), 200, 200); } int length = AppDomain.CurrentDomain.BaseDirectory.LastIndexOf(AppDomain.CurrentDomain.FriendlyName) + AppDomain.CurrentDomain.FriendlyName.Length + 1; string sub = AppDomain.CurrentDomain.BaseDirectory.Substring(0, length); var fileName = sub + "wwwroot\\chart\\Mode-5000.bmp"; n.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg); StateHasChanged(); } } }
问题原因
- WebView缓存机制:Blazor WebView会缓存静态资源,即使文件已更新,仍会加载缓存版本,只有重启应用才会重新读取文件。
- 组件未触发更新:
currentChartPath的值没有变化,ImageViewer组件不会主动重新请求资源。 - wwwroot特性限制:MAUI/Razor中
wwwroot是静态资源目录,运行时不会自动监测文件变化并重载,无需也无法直接重载整个wwwroot。
解决办法
方法1:添加随机参数规避缓存
在图片URL后添加时间戳或随机字符串,让WebView认为是新资源,强制重新加载:
public async Task CreateChartAsync() // 修正异步方法签名,替换async void为async Task { var n = new Bitmap(314, 314); using (var g = Graphics.FromImage(n)) { g.DrawString("hallo test", new System.Drawing.Font("Tahoma", 8), new SolidBrush(System.Drawing.Color.Red), 200, 200); } // 优化路径获取方式,避免硬编码错误 var fileName = Path.Combine(AppContext.BaseDirectory, "wwwroot", "chart", "Mode-5000.jpg"); n.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg); // 添加时间戳参数,触发资源重新加载 currentChartPath = $"./chart/Mode-5000.jpg?t={DateTime.Now.Ticks}"; StateHasChanged(); }
注:原代码中保存格式是Jpeg但路径后缀是bmp,建议统一后缀避免混淆。
方法2:使用Base64直接传递图片(更高效)
无需保存到文件系统,直接将图片转为Base64字符串传递给组件,跳过缓存和文件读取问题:
private string currentChartBase64; public async Task CreateChartAsync() { using var n = new Bitmap(314, 314); using (var g = Graphics.FromImage(n)) { g.DrawString("hallo test", new System.Drawing.Font("Tahoma", 8), new SolidBrush(System.Drawing.Color.Red), 200, 200); } // 将图片转为Base64格式 using var ms = new MemoryStream(); n.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); var bytes = ms.ToArray(); currentChartBase64 = $"data:image/jpeg;base64,{Convert.ToBase64String(bytes)}"; StateHasChanged(); }
修改Razor中的ImageViewer:
<ImageViewer Url="@currentChartBase64" FitMode="ObjectFitMode.Fill" />
方法3:优化路径获取方式(可选)
原代码中获取wwwroot路径的方式复杂易出错,可通过注入IWebHostEnvironment获取标准路径:
[Inject] private IWebHostEnvironment Env { get; set; } public async Task CreateChartAsync() { // ... 生成图片代码 ... var fileName = Path.Combine(Env.WebRootPath, "chart", "Mode-5000.jpg"); n.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg); // ... 更新路径代码 ... }
问题效果对比
图片已生成但未显示(原问题)




重启应用后显示(原正常效果)


内容的提问来源于stack exchange,提问作者Üh Lieh
相关产品推荐
相关产品推荐

