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 ...
随机推荐
- 【每日一题】35. [CQOI2009]中位数图 (前缀和,贡献值计算)
补题链接:Here 算法涉及:前缀和,贡献值计算 经典中位数计数问题,记得以前百度之星也出过类似的题,这道题有一个限定范围是要奇数区间的 我们很容易想到,奇数下标到偶数下标或者偶数下标到奇数下标的长度 ...
- 8、SpringBoot 事务
系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...
- LightOJ 1094
题意:就是求一个树的直径,也就是求任意两点的最大距离. 做法:跑两遍DFS,详见代码. #include<iostream> #include<cstdio> #include ...
- 【ThreadX-NetX】Azure RTOS NetX概述
Azure RTOS NetX是工业级TCP / IP IPv4嵌入式网络堆栈,专门针对深度嵌入式,实时和IoT应用程序而设计.Azure RTOS NetX是Microsoft最初的IPv4网络堆栈 ...
- [转帖]细说:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4
https://www.cnblogs.com/malecrab/p/5300503.html 1. Unicode与ISO 10646 全世界很多个国家都在为自己的文字编码,并且互不想通,不同的语言 ...
- [转帖]46岁加入谷歌,51岁发明Go,他的编程原则影响了一大批程序员!
https://www.zhihu.com/tardis/zm/art/551945410?source_id=1005 今年3月,万众瞩目的Go 1.18版本发布,Go终于开始支持泛型了!该版本不仅 ...
- [转帖]062、监控指标之PD
PD相关 Grafana 监控 PD -> PD Dashboard 是否存在异常状态的TiKV Grafana 监控 PD -> Region health 大表清理后,出现了大量的空r ...
- [转帖]Java 获取 Kafka 指定 topic 的消息总量
发表于 2020-11-29 分类于 Java , Apache , JavaClass , Kafka Valine: 0 Kafka Consumer API Kafka 提供了两套 API ...
- [转帖]初探Linux CPU动态调频与实测
https://zhuanlan.zhihu.com/p/33753019 关于 本文主要涉及Linux CPUFreq子系统是什么,为什么需要,怎么用. 并解决在实际测试中遇到的三个问题: scal ...
- ESXi6.7安装Win11的方法
背景 公司里面要进行新的操作系统验证了. 之前Win10 Win7 Win8 都比较简单. 就是现在Win11有了TPM非常繁琐. 今天必须得搞一把了,就简单搜索了下. 发现还是可以解决的. 然后记录 ...