You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin从SQLite数据库导出PDF遇权限拒绝异常求助

解决Xamarin导出PDF时的UnauthorizedAccessException问题

你遇到的错误是因为直接尝试写入系统根目录,而Android/iOS都严格限制了对根目录的直接访问,必须使用系统允许的存储路径。以下是两种可行的解决方案:

方案一:使用应用私有存储目录(无需额外权限)

这个路径只有你的应用能访问,适合不需要用户在外部文件管理器查看的场景,代码实现简单:

var item = e.CurrentSelection[0] as SamplesData;
byte[] pdfBytes = (byte[])item.PDF;
string fileName = "kms.pdf";

// 获取应用私有存储目录路径
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), fileName);

// 写入文件(using语句会自动释放资源,比手动Close更安全)
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
    fs.Write(pdfBytes, 0, pdfBytes.Length);
}

// 打开文件
File.OpenRead(filePath);

方案二:导出到公共存储目录(让用户可在文件管理器查看)

如果需要把PDF导出到用户能直接访问的位置(比如下载文件夹),需要处理不同平台的权限和路径:

Android端实现

  1. 先在AndroidManifest.xml中添加权限:
<!-- Android 12及以下需要的读写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 13+ 针对文档的读取权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_DOCUMENTS" android:minSdkVersion="33" />
  1. 动态申请权限并写入文件:
var item = e.CurrentSelection[0] as SamplesData;
byte[] pdfBytes = (byte[])item.PDF;
string fileName = "kms.pdf";

// 获取公共下载目录路径
string downloadsPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
string filePath = Path.Combine(downloadsPath, fileName);

// Android 6.0+ 需要动态申请权限
if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
{
    ActivityCompat.RequestPermissions((Android.App.Activity)Xamarin.Essentials.Platform.CurrentActivity, 
                                      new string[] { Manifest.Permission.WriteExternalStorage }, 1);
    // 权限申请结果会在OnRequestPermissionsResult回调中返回,拿到权限后再执行写入操作
    return;
}

// 写入文件
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
    fs.Write(pdfBytes, 0, pdfBytes.Length);
}

// 通知系统媒体扫描器,让文件立刻在文件管理器中显示
MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] { filePath }, null, null);

iOS端实现

iOS可以写入应用的Documents目录,若要让用户在系统文件应用中看到,还需配置Info.plist:

var item = e.CurrentSelection[0] as SamplesData;
byte[] pdfBytes = (byte[])item.PDF;
string fileName = "kms.pdf";

// 获取应用Documents目录路径
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filePath = Path.Combine(documentsPath, fileName);

// 写入文件
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
    fs.Write(pdfBytes, 0, pdfBytes.Length);
}

然后在Info.plist中添加以下配置,开启文件共享:

<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>

内容的提问来源于stack exchange,提问作者mohammad esawe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:34:53