MAUI Blazor 加载本地图片的解决方案
前言
为了解决MAUI Blazor无法加载本地图片,https://github.com/dotnet/maui/issues/2907,所以写了这篇文章。
有token大佬珠玉在前,https://www.cnblogs.com/hejiale010426/p/17073079.html ,以及微软文档的补充,https://learn.microsoft.com/zh-cn/aspnet/core/blazor/images?view=aspnetcore-7.0#stream-image-data,才能写出这篇文章,特此感谢。
解决的思路是判断路径是本机路径,如果是,调用js为它生成blob,将本机路径与blob的url对应上通过字典存储起来,主动释放时从字典移除。
原理上与token大佬的文章没有什么太大区别,最主要的是增加了缓存机制
正文
添加所需代码
- 添加接口ILocalImageService
//https://github.com/dotnet/maui/issues/2907
public interface ILocalImageService
{
// 为本地路径的图片创建blob,并返回blob的url,若不是本地路径会直接返回
Task<string> ToUrl(string path);
// 调用js,释放图片的blob
Task RevokeUrl(string path);
}
- 添加实现类
public class LocalImageService : ILocalImageService
{
private readonly IJSRuntime JS;
private IJSObjectReference module = default!;
//存储已生成的图片,将图片本机路径与图片blob的url联系起来
private static readonly ConcurrentDictionary<string, string> urls = new();
//控制访问单个图片资源的线程数量,若图片blob在生成中,将等待
private static readonly ConcurrentDictionary<string, SemaphoreSlim> semaphores = new();
public LocalImageService(IJSRuntime jS)
{
JS = jS;
}
//为本地路径的图片创建blob,并返回blob的url,若不是本地路径会直接返回
public async Task<string> ToUrl(string path)
{
await InitModule();
if (!File.Exists(path))
{
return path;
}
SemaphoreSlim semaphore = semaphores.GetOrAdd(path, _ => new SemaphoreSlim(1));
await semaphore.WaitAsync();
try
{
if (urls.TryGetValue(path, out string? url))
{
return url;
}
else
{
string newUrl = await GenerateImageUrl(path);
urls.TryAdd(path, newUrl);
return newUrl;
}
}
finally
{
semaphore.Release();
}
}
//调用js,生成图片的blob
private async Task<string> GenerateImageUrl(string path)
{
using var imageStream = File.OpenRead(path);
var dotnetImageStream = new DotNetStreamReference(imageStream);
var url = await module.InvokeAsync<string>("streamToUrl", new object[1] { dotnetImageStream });
return url;
}
//调用js,释放图片的blob
public async Task RevokeUrl(string path)
{
await InitModule();
if(string.IsNullOrWhiteSpace(path))
{
return;
}
if (urls.ContainsKey(path))
{
urls.TryRemove(path, out string? url);
await module.InvokeVoidAsync("revokeUrl", new object[1] { url! });
}
}
//初始化JS模块
private async Task InitModule()
{
module ??= await JS!.InvokeAsync<IJSObjectReference>("import", "./js/getLocalImage.js");
}
}
- 在wwwroot/js中添加getLocalImage.js
/*出自 https://www.cnblogs.com/hejiale010426/p/17073079.html,有修改*/
/** 将stream转url对象 */
export async function streamToUrl(imageStream) {
// 适配webview和web
const arrayBuffer = await imageStream.arrayBuffer();
const blob = new Blob([arrayBuffer]);
return (window.URL || window.webkitURL || window || {}).createObjectURL(blob);
}
/**
* 释放url对象,因为createObjectURL创建的对象一直会存在可能会占用过多的内存,请注意释放
*/
export function revokeUrl(url) {
(window.URL || window.webkitURL || window || {}).revokeObjectURL(url);
}
- 在MauiProgram.cs中添加以下代码
builder.Services.AddScoped<ILocalImageService, LocalImageService>();
注意事项
使用时一定要注意释放,当你不需要这个图片时主动释放它。如果它需要经常显示,那么不必释放,因为生成比较大的图片在安卓上是比较慢的。
最终效果


源码
源码放在GitHub上了,https://github.com/Yu-Core/MAUIBlazorLoadLocalImage
MAUI Blazor 加载本地图片的解决方案的更多相关文章
- android ImageLoader加载本地图片的工具类
import android.widget.ImageView; import com.nostra13.universalimageloader.core.ImageLoader; /** * 异步 ...
- UIWebView如何加载本地图片
UIWebView如何加载本地图片 UIWebView加载本地图片是有实用价值的.比方说,有时候我们需要本地加载静态页来显示相关帮助信息,而这些帮助信息当中含有很多很多的富文本,用代码实现难度较大,这 ...
- angular 图片加载失败 情况处理? 如何在ionic中加载本地图片 ?
1.angular 图片加载失败 情况处理 在directive中定义组件,在ng-src错误时,调用err-src app.directive('errSrc',function(){ return ...
- Flutter学习笔记(19)--加载本地图片
如需转载,请注明出处:Flutter学习笔记(19)--加载本地图片 上一篇博客正好用到了本地的图片,记录一下用法: 首先新建一个文件夹,这个文件夹要跟目录下 然后在pubspec.yaml里面声明出 ...
- !!!myeclipse 上加载本地图片问题,无法加载问题
出现无法加载本地图片的问题, 原因就是把图片放到了本地项目中的image了,但是myeclipse上没有刷新 这样以后 本地的图片比在线的要快 低级错误,诶!
- 用UIWebView加载本地图片和gif图
加载gif图: NSData *gif = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@" ...
- vue如何动态加载本地图片
大家好,我是前端队长Daotin,想要获取更多前端精彩内容,关注我(全网同名),解锁前端成长新姿势. 以下正文: 今天遇到一个在vue文件中引入本地图片的问题,于是有了这篇文章. 通常,我们的一个im ...
- UIImage加载本地图片的两种方式
UIImage加载图片方式一般有两种: (1)imagedNamed初始化:默认加载图片成功后会内存中缓存图片,这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象.如果缓存中没有找到相应的图片 ...
- Unity加载本地图片的2种方式
1. 使用 WWW 加载,详细查看 unity3d 官方文档. 2. 使用 System.IO 加载,lua 代码如下: local File = luanet.import_type("S ...
- fresco加载本地图片、gif资源
首先 来看看fresco 是个神马东西 https://github.com/facebook/fresco 这个是fresco的一个官方gifhub 官网为http://frescolib.org/ ...
随机推荐
- Django笔记二十六之数据库函数之数学公式函数
本文首发于公众号:Hunter后端 原文链接:Django笔记二十六之数据库函数之数学公式函数 这一篇来介绍一下公式函数,主要是数学公式. 其中 sin,cos 这种大多数情况下用不上的就不介绍了,主 ...
- CF1738EBalance Addicts
CF1738EBalance Addicts 原题: CF1738EBalance Addicts 目录 CF1738EBalance Addicts 题目大意 做法 思路 注意 code 题目大意 ...
- 09-devserver
const {resolve} = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module.ex ...
- 笔记:C++学习之旅---面向对象程序的设计1
笔记:C++学习之旅---面向对象程序的设计1 面向对象的主要特征 1.抽象 2.封装 3.继承 4.多态 抽象:将程序的每一部分都看作一个抽象的对象,即程序有一组抽象的对象组成的更复杂点,这些对象根 ...
- Java8 Stream流的合并
最近的需求里有这样一个场景,要校验一个集合中每个对象的多个Id的有效性.比如一个Customer对象,有3个Id:id1,id2,id3,要把这些Id全部取出来,然后去数据库里查询它是否存在. @Da ...
- ai问答:使用 Vue3 组合式API 和 TS 父子组件共享数据
这是一个使用 Vue3 组合式 API 和 TypeScript 的简单父子组件共享数据示例 父组件 Parent.vue: <template> <div> <p> ...
- Vue3 +element-plus+ wangEditor 富文本编辑器+前端七牛云上传
我用的vue3,element-plus ,没用ts 搭建wangEditor 参考 地址 https://www.cnblogs.com/xbxxf/p/16791084.html 七牛云安装参考地 ...
- Django4全栈进阶之路11 view视图
在 Django 4 中,视图(View)是一个处理请求并返回响应的 Python 函数或类的组合.视图函数通常是处理请求的主要逻辑,因此它是 Django Web 应用程序的重要组成部分. 视图函数 ...
- Django4全栈进阶之路2 创建虚拟环境、项目、app应用、启动运行项目
一.安装虚拟环境: 命令:pip3 install virtualenv 二.安装管理工具: 命令:pip3 install virtualenvwrapper 三.新建: 命令:python -m ...
- Flutter编写的数独游戏
一个使用Flutter编写的每日数独小游戏,支持Android和ios.代码已上传到github:https://github.com/huhx/flutter_sudoku Library 状态管理 ...