.NET7 Blazor Server Hybrid安卓端文件下载故障及存储优化需求
问题描述
基于.NET7开发Blazor Server Hybrid应用,Razor组件封装在RCL中,同时部署Web端与Blazor MAUI安卓端,遇到如下问题:
- Web端通过BlazorDownloadFile NuGet包可正常从SQL表Blob字段下载图片,但安卓端完全失效
- 已在AndroidManifest.xml配置
ACCESS_NETWORK_STATE、INTERNET、WRITE_EXTERNAL_STORAGE权限,无调用栈报错,仅Output日志出现[libEGL]相关错误 - 尝试多线程下载、调整MainPage代码后仍无效,还出现Blob错误
- 自行实现文件写入逻辑后,文件可保存至
/data/user/0/com.companyname.myappname/files,但无下载提示,且该路径不易查找,希望将文件保存至手机相册目录并添加下载完成提示
解决方案
1. 适配安卓端存储到相册
要将图片保存到手机相册,需针对安卓版本做不同处理:
- 权限适配:Android 13及以上需额外申请
READ_MEDIA_IMAGES/WRITE_MEDIA_IMAGES权限,且必须动态申请(仅清单配置无效) - 媒体存储API调用:直接写入相册需通过MediaStore API,避免直接操作文件路径,示例代码:
using Android.Content; using Android.OS; using Android.Provider; using System.IO; public async Task SaveImageToGallery(byte[] imageBytes, string fileName) { var mimeType = "image/jpeg"; var values = new ContentValues(); values.Put(MediaStore.Images.Media.Columns.DisplayName, fileName); values.Put(MediaStore.Images.Media.Columns.MimeType, mimeType); if (Build.VERSION.SdkInt >= BuildVersionCodes.Q) { values.Put(MediaStore.Images.Media.Columns.RelativePath, "DCIM/MyAppImages"); values.Put(MediaStore.Images.Media.Columns.IsPending, 1); var uri = Android.App.Application.Context.ContentResolver.Insert(MediaStore.Images.Media.ExternalContentUri, values); using (var stream = Android.App.Application.Context.ContentResolver.OpenOutputStream(uri)) { await stream.WriteAsync(imageBytes); } values.Put(MediaStore.Images.Media.Columns.IsPending, 0); Android.App.Application.Context.ContentResolver.Update(uri, values, null, null); } else { var directoryPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "DCIM/MyAppImages"); Directory.CreateDirectory(directoryPath); var filePath = Path.Combine(directoryPath, fileName); await File.WriteAllBytesAsync(filePath, imageBytes); // 通知媒体扫描器刷新相册 MediaScannerConnection.ScanFile(Android.App.Application.Context, new[] { filePath }, new[] { mimeType }, null); } }
2. 添加下载完成提示
通过原生Toast实现安卓端的下载提示:
- 定义跨平台接口:
public interface IToastService { void ShowToast(string message); }
- 安卓端实现:
using Android.Widget; public class AndroidToastService : IToastService { public void ShowToast(string message) { Toast.MakeText(Platform.CurrentActivity, message, ToastLength.Long).Show(); } }
- 在
MauiProgram.cs注册服务:
builder.Services.AddSingleton<IToastService, AndroidToastService>();
- 在Razor组件中注入并调用:
@inject IToastService ToastService // 下载完成后触发提示 ToastService.ShowToast("图片已成功保存至相册");
3. 跨端下载的适配方案
由于BlazorDownloadFile在安卓端存在兼容性问题,建议通过依赖注入+平台特定实现做跨端适配:
- 在RCL中定义下载接口,Web端继续用BlazorDownloadFile实现,安卓端用上述原生存储逻辑实现,通过依赖注入自动匹配平台实现
内容的提问来源于stack exchange,提问作者user13714356
相关产品推荐
相关产品推荐

