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

Xamarin写入内部存储文件时出现Permission Denied错误,求解决方案

问题:拍照保存至应用内部存储时触发UnauthorizedAccessException

我尝试用以下代码实现拍照并保存到应用内部存储:

var photo = await MediaPicker.CapturePhotoAsync();
string maindir = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "Pictures");
string filename = System.DateTime.Now.ToString("yyyyMMdd_HHmmss") + System.IO.Path.GetExtension(photo.FileName);
var newFile = Path.Combine(maindir, filename);
Directory.CreateDirectory(newFile);
using (var stream = await photo.OpenReadAsync())
{
    using (var newStream = File.OpenWrite(newFile))
    {
        await stream.CopyToAsync(newStream);
    }
}

通过Xamarin.Essentials.FileSystem.AppDataDirectory获取的是应用专属内部存储目录(已额外配置外部存储写入权限,但无作用),代码基本照搬Xamarin.Essentials官方文档。

在File.OpenWrite行触发UnauthorizedAccessException,提示:Access to the path '/data/user/0/com.companyname.peerpeek/files/Pictures/20231115_154707.jpg' is denied。

按资料来看这种情况不该发生,请问是Bug还是我漏了什么?

测试环境:Pixel 5模拟器(Android 13)、实体机(Android 12)均出现该错误。

补充完整异常信息:

System.UnauthorizedAccessException: Access to the path '/data/user/0/com.companyname.peerpeek/files/Pictures/20231115_163542.jpg' is denied.
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x000e7] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/FileStream.cs:196 
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/FileStream.cs:91 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
  at System.IO.File.OpenWrite (System.String path) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.IO.FileSystem/src/System/IO/File.cs:271 
  at PeerPeek.MainPage.LoadPhotoAsync (Xamarin.Essentials.FileResult photo) [0x00187] in C:\Users\nicksa\source\repos\PeerPeek\PeerPeek\PeerPeek\MainPage.xaml.cs:88

解答

问题出在这行代码:

Directory.CreateDirectory(newFile);

你把带文件名的完整路径传给了Directory.CreateDirectory,这会创建一个以.jpg为后缀的目录,而非创建保存文件所需的父目录。后续尝试往这个目录路径写入文件,自然会触发权限拒绝异常。

正确的做法是先创建父目录maindir,而非带文件名的路径:

修正后的代码:

var photo = await MediaPicker.CapturePhotoAsync();
string maindir = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "Pictures");
// 先创建保存图片的父目录
Directory.CreateDirectory(maindir);
string filename = System.DateTime.Now.ToString("yyyyMMdd_HHmmss") + System.IO.Path.GetExtension(photo.FileName);
var newFile = Path.Combine(maindir, filename);

using (var stream = await photo.OpenReadAsync())
{
    using (var newStream = File.OpenWrite(newFile))
    {
        await stream.CopyToAsync(newStream);
    }
}

另外,你额外配置的外部存储权限在这里是多余的——FileSystem.AppDataDirectory指向的是应用专属的内部存储目录,应用对该目录拥有完全读写权限,无需额外申请权限。


内容的提问来源于stack exchange,提问作者Nick Sabbe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:44:54