啊... ...

一通操作下来感觉就是两个字 折磨

跨平台有跨平台的好处 但框架本身支持的有限 很多东西做起来很曲折 哎

这里总结一下笔者为了折腾本地图片显示的尝试

为什么要做本地图片展示呢 如果是做需要网络连接的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显示本地图片的更多相关文章

  1. Android ImageView显示本地图片

    Android ImageView 显示本地图片 布局文件 <?xml version="1.0" encoding="utf-8"?> <R ...

  2. Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

    版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/1873 ...

  3. Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果

    大家好!过完年回来到现在差不多一个月没写文章了,一是觉得不知道写哪些方面的文章,没有好的题材来写,二是因为自己的一些私事给耽误了,所以过完年的第一篇文章到现在才发表出来,2014年我还是会继续在CSD ...

  4. Slog71_选取、上传和显示本地图片GET !(微信小程序之云开发-全栈时代3)

    ArthurSlog SLog-71 Year·1 Guangzhou·China Sep 12th 2018 ArthurSlog Page GitHub NPM Package Page 掘金主页 ...

  5. Atitit. html 使用js显示本地图片的设计方案.doc

    Atitit. html 使用js显示本地图片的设计方案.doc 1.  Local mode  是可以的..web模式走有的不能兰.1 2. IE8.0 显示本地图片 img.src=本地图片路径无 ...

  6. Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案

    Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案 1. IE8.0 显示本地图片 img.src=本地图片路径无效的解决方案1 1.1. div来完成  ...

  7. 在InternetExplorer.Application中显示本地图片

    忘记了,喜欢一个人的感觉 Demon's Blog  »  程序设计  »  在InternetExplorer.Application中显示本地图片 « 对VBS效率的再思考——处理二进制数据 Wo ...

  8. tomcat中显示本地图片①(未解决)

    <本模块文仅作为学习过程中的自我总结,有需要可参看,欢迎指导与提出建议,很多地方可能断章取义,理解不到位,虚心求学.谢谢!> 资料查阅原因:2018/7/10(做项目中显示详情页面,从数据 ...

  9. SpringBoot之显示本地图片范例

    controller // 扫描指定目录下的图片进行展示 @RequestMapping("/showPics") public ModelAndView showPics(Mod ...

  10. HTML5 Canvas显示本地图片实例1、Canvas预览图片实例1

    1.前台代码: <input id="fileOne" type="file" /> <canvas id="canvasOne&q ...

随机推荐

  1. 复旦大学2020考研机试题-编程能力摸底试题(A-E)

    A.斗牛 给定五个0~9范围内的整数a1,a2,a3,a4,a5.如果能从五个整数中选出三个并且这三个整数的和为10的倍数(包括0),那么这五个整数的权值即为剩下两个没被选出来的整数的和对10取余的结 ...

  2. ios-class-guard - iOS代码混淆与加固实践

    ​ 目录 ios-class-guard - iOS代码混淆与加固实践 摘要 引言 一.class-dump 二.ios-class-guard 混淆原理 三.ios-class-guard 混淆结果 ...

  3. location对象的方法

    location.assign() 跟href一样,可以跳转页面(也称为重定向页面). location.replace() 替换当前页面,因为不记录历史,所以不能后退页面. location.rel ...

  4. 这才是你应该了解的Redis数据结构!

    深入了解Redis数据结构 Redis,作为一种高性能的内存数据库,支持多种数据结构,从简单的字符串到复杂的哈希表.在这篇博文中,我们将深入探讨Redis的一些主要数据结构,并通过详细的例子展示它们的 ...

  5. freeswitch-1.10.7性能测试

    概述 freeswitch 是一款简单好用的开源软交换平台. freeswitch-1.10.7是比较新的版本,使用时间比较短,需要一个可参考的性能指标,作为实际使用过程中的配置指导. 环境 cent ...

  6. Asp.Net Core造轮之旅:逐步构建自己的开发框架-目录

    本系列适用于已有一定.NET开发基础,学习asp.net core人士. 基础篇 asp.net core之Startup asp.net core之依赖注入 asp.net core之中间件 asp ...

  7. ORA-00947:Not enough values (没有足够的值)

    1.问题 2.解决方式 大概率是关系表实际列数大于你所填的元素个数,请检查是否有疏漏的列即可. 我这里是以为代理键直接忽略不写即可,没有标明具体插入列,但是还是得标明才行 --创建图书目录表TITLE ...

  8. Linux 中常用的基础命令

    by emanjusaka from https://www.emanjusaka.top/2024/01/linux-base-command 彼岸花开可奈何 本文欢迎分享与聚合,全文转载请留下原文 ...

  9. java - 对象装载数据返回

    1. 创建 Phone 类 package class_object; public class Phone { String brand; String color; double price; v ...

  10. 2.4G+MCU低功耗二合一芯片SI24R03

    2.4G+MCU低功耗二合一芯片SI24R03 1 简介 Si24R03 是一款高度集成的低功耗 SOC 芯片,其集成了基于 RISC-V 核的低功耗 MCU 和 工作在 2.4GHz ISM 频段的 ...