blazor maui hybrid app显示本地图片
啊... ...
一通操作下来感觉就是两个字 折磨
跨平台有跨平台的好处 但框架本身支持的有限 很多东西做起来很曲折 哎
这里总结一下笔者为了折腾本地图片显示的尝试
为什么要做本地图片展示呢 如果是做需要网络连接的app 这个一般是不需要的(要做上传前预览/编辑的话还是要的)
但对于离线的app肯定是要的 总会有场景用户导入图片/文件之类的吧
笔者只测试了windows和安卓这两个平台,mac和iOS因为没有设备和开发者账号所以调试不了
复制到wwwroot
这是最简单直接的方法,什么都不用改,把图片复制到wwwroot下然后直接使用图片地址就行了
代码如下:
public async Task PickAndShow(PickOptions options)
{
try
{
var result = await FilePicker.Default.PickAsync(options);
if (result != null)
{
await using var stream = await result.OpenReadAsync();
var originalFileName = result.FileName;
var extension = Path.GetExtension(originalFileName);
var targetFileName = Guid.NewGuid() + extension;
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "images", targetFileName);
Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "images"));
await using var targetStream = new FileStream(path, FileMode.Create);
Debug.WriteLine($"copy path:{path}");
await stream.CopyToAsync(targetStream);
_objUrl = $"images/{targetFileName}";
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
这个的优点就是简单直接
缺点就是安卓不支持... 安卓的wwwroot在app bundle里 只能读不能写
适合只需要windows的使用
但你只需要windows 还用maui是不是有
base64/objectURL
这两个我一起说 因为原理是一样的
存在sqlite appdata或者其他什么地方
需要用的时候读取转化为base64和objectURL
但是使用base64的时候我发现了很严重的内存泄漏,传了很多图片测试之后应用的内存直接炸了.
见: https://stackoverflow.com/questions/77513507/how-to-avoid-memory-leaks-when-using-base64-images-in-blazor
可能是我用的png有关,但他的确会造成内存较大的消耗,并且有不必要的开销,你转成base64,浏览器还得给他转回来.
用objectURL是个更好的选择
在index.html中放入这段代码:
<script>
window.createObjectURL = async (imageStream) => {
const arrayBuffer = await imageStream.arrayBuffer();
const blob = new Blob([arrayBuffer]);
return URL.createObjectURL(blob);
}
window.revokeObjectURL = (url) => {
URL.revokeObjectURL(url);
}
</script>
扩展一下IJSRuntime,这是为了方便使用,也可以直接调,都是一样的:
public static class IJSRuntimeExtensions
{
public static ValueTask<string> CreateObjectUrl(this IJSRuntime js, Stream stream, bool leaveOpen = false)
{
var dotNetStreamReference = new DotNetStreamReference(stream, leaveOpen);
return js.InvokeAsync<string>("createObjectURL", dotNetStreamReference);
}
public static async Task RevokeObjectUrl(this IJSRuntime js, string? url)
{
Debug.WriteLine($"Revoke call url {url}");
if (url is not null)
{
await js.InvokeVoidAsync("revokeObjectURL", url);
}
}
}
哪里需要用调用一下获得objectURL即可
复制到appdata下 覆盖CreateFileProvider
从爆栈上发现的,测试了下windows和安卓上都可用,意外的简单直接.
见:
https://stackoverflow.com/a/75282680/2078863
public class CustomFilesBlazorWebView : BlazorWebView
{
public override IFileProvider CreateFileProvider(string contentRootDir)
{
var lPhysicalFiles = new PhysicalFileProvider(FileSystem.Current.AppDataDirectory);
return new CompositeFileProvider(lPhysicalFiles, base.CreateFileProvider(contentRootDir));
}
}
然后用这个替换原本的BlazorWebView即可.
之后就将文件复制到Appdata下:
public static readonly string ImageDir = "image";
public async Task<string> CopyToImageDir(byte[] bytes, string originalFileName)
{
var appFilePath = Path.Combine(GetImageDirPath(), CreateNewName(originalFileName));
Directory.CreateDirectory(GetImageDirPath());
await using var fileStream = File.Create(appFilePath);
await fileStream.WriteAsync(bytes);
return appFilePath;
}
public string GetImageDirPath()
{
return Path.Combine(FileSystem.AppDataDirectory, ImageDir);
}
private string CreateNewName(string originalFileName)
{
var extension = Path.GetExtension(originalFileName);
var uuid = Guid.NewGuid().ToString();
var newFileName = $"{Path.GetFileNameWithoutExtension(originalFileName)}_{uuid}{extension}";
return newFileName;
}
url使用image/filename即可
这些方案都不可避免要将文件复制都某个地方.
其实优化下可以直接读原始文件, 但是不同平台限制不太一样, 比如在安卓上FilePicker返回的fullPath是cache地址不是实际地址, 需要自己写native代码用安卓原生的文件选择.
其他还有不少大佬的方案,这里只做几个实现比较简单的总结.
市面上有许多由资深开发者提出的复杂方案,但在这里,我只总结了几个实现起来相对简单的方法.
唉,MAUI本身的使用确实颇具挑战性.虽然将Blazor集成进UI在某种程度上缓解了这一问题,但由于其跨平台的特性,很多功能似乎都不尽如人意.
初看上去,基础的使用似乎没什么问题,但一旦动手实现更复杂的功能,就会发现受到了各种限制.想要突破这些限制,就必须编写与平台相关的代码,而这又要求你必须深入了解Windows、安卓和iOS等系统的原生代码是如何编写的.
这种局面确实令人尴尬,这或许也是跨平台框架普遍存在的问题.
微软的努力将决定未来的发展,但从他们那边来看,情况似乎并不乐观.
就以本文读取本地图片的问题为例:
https://github.com/dotnet/maui/issues/2907
https://github.com/dotnet/aspnetcore/issues/25274
早在2021年甚至2020年,就有人提出了这个问题.
经过多个相关问题的讨论,认为在.NET 7中实现这一功能风险太大,决定推迟到.NET 8.
mkArtakMSFT modified the milestones: Backlog, .NET 7 Planning on Nov 6, 2021
danroth27 modified the milestones: .NET 7 Planning, .NET 8 Planning on Aug 24, 2022
While we have made progress on this feature, at this point we think the risk is too high to include this in the .NET 7 release. Moving to .NET 8.2023-06-30 bot: We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
然而,即便.NET 8已经发布,这个功能依旧没有得到官方的实现, 只有各种workaround……这实在令人沮丧.
MAUI给人的感觉好像是一个被遗弃的项目.随着.NET 9或.NET 10的推出,微软可能会宣布停止支持MAUI,并推出另一个全新的框架.
毕竟微软的作风一贯如此.
相关参考链接:
Work with images in ASP.NET Core Blazor
[Bug] Not allowed to load local resource for Android
Blazor Image component to display images that are not accessible through HTTP endpoints
How to display local image as well as resources image in .Net MAUI Blazor
Overriding CreateFileProvider for BlazorWebView throws exception
博客: blazor maui hybrid app显示本地图片
blazor maui hybrid app显示本地图片的更多相关文章
- Android ImageView显示本地图片
Android ImageView 显示本地图片 布局文件 <?xml version="1.0" encoding="utf-8"?> <R ...
- Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果
版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/1873 ...
- Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果
大家好!过完年回来到现在差不多一个月没写文章了,一是觉得不知道写哪些方面的文章,没有好的题材来写,二是因为自己的一些私事给耽误了,所以过完年的第一篇文章到现在才发表出来,2014年我还是会继续在CSD ...
- Slog71_选取、上传和显示本地图片GET !(微信小程序之云开发-全栈时代3)
ArthurSlog SLog-71 Year·1 Guangzhou·China Sep 12th 2018 ArthurSlog Page GitHub NPM Package Page 掘金主页 ...
- Atitit. html 使用js显示本地图片的设计方案.doc
Atitit. html 使用js显示本地图片的设计方案.doc 1. Local mode 是可以的..web模式走有的不能兰.1 2. IE8.0 显示本地图片 img.src=本地图片路径无 ...
- Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案
Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案 1. IE8.0 显示本地图片 img.src=本地图片路径无效的解决方案1 1.1. div来完成 ...
- 在InternetExplorer.Application中显示本地图片
忘记了,喜欢一个人的感觉 Demon's Blog » 程序设计 » 在InternetExplorer.Application中显示本地图片 « 对VBS效率的再思考——处理二进制数据 Wo ...
- tomcat中显示本地图片①(未解决)
<本模块文仅作为学习过程中的自我总结,有需要可参看,欢迎指导与提出建议,很多地方可能断章取义,理解不到位,虚心求学.谢谢!> 资料查阅原因:2018/7/10(做项目中显示详情页面,从数据 ...
- SpringBoot之显示本地图片范例
controller // 扫描指定目录下的图片进行展示 @RequestMapping("/showPics") public ModelAndView showPics(Mod ...
- HTML5 Canvas显示本地图片实例1、Canvas预览图片实例1
1.前台代码: <input id="fileOne" type="file" /> <canvas id="canvasOne&q ...
随机推荐
- 第五届蓝桥杯(2014)C/C++大学A组省赛题解
第一题.猜年龄 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍".小明又补充说:"她们可不是双胞胎,年龄差肯定也不超过8岁 ...
- 七、java操作swift对象存储(动态大对象)
系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...
- 2023年AI领域行业洞察,看这30个统计数据就够了!
PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全.密码学.联邦学习.同态加密等隐私计算领域的技术和内容. 随着AIGC的爆火,企业越来越多地开始采用生成式人工智能.自然语 ...
- 面试重点:webpack
webpack 熟练掌握Webpack的常用配置,能够自己构建前端环境,并进行项目优化; 001.谈谈你对webpack的看法: webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编 ...
- python之logging日志
一.logging介绍: 使用 logging.debug(text)来打印信息,info等的使用方法与debug一致,都只有一个位置参数 默认日志界别为:会输出warning以上的信息,代码示例: ...
- java基础(16)--super与this
一.this简介 1.this. this() 2.静态方法无法使用 3.不省略的情况:区分局部变量与实例变量,比如set方法中用到 二.super简介 1.只能出现在实例方法或构造方法中 2. ...
- C++ std::initializer_list 实现原理勘误
今天正在看侯捷<C++ 新标准 C++11-14>的视频,里面讲到 std::initializer_list 的实现原理,并且把源码贴出来. /// initializer_list t ...
- 基于Tensorflow技术开发的计算机毕业设计辅助生成器(使用AI大模型技术)
这是一个辅助生成计算机毕业设计的工具,可以自动完成毕业设计的源码.它基于几百个github上面开源的java和python项目,运用tensorflow技术,训练出了AI大模型.基本实现了计算机毕业设 ...
- 【转】获取本地图片的URL
在写博客插入图片时,许多时候需要提供图片的url地址.作为菜鸡的我,自然是一脸懵逼.那么什么是所谓的url地址呢?又该如何获取图片的url地址呢? 首先来看一下度娘对url地址的解释:url是 ...
- 如何部署两个JMS网关,形成双机热备
大家使用JMS的过程中,可能会留意到,不管是微服务在注册时,还是RemoteClient构造时,所指向的网关都是一个NetAddress数组,之所以网关地址是多个,而不是一个,那是因为网关是一个双击热 ...