Xamarin.Forms在文件系统中保存文件

8
我尝试从网络下载文件并保存到任何Environment.SpecialFolder位置。无论我采用什么方法,我总是会得到System.UnauthorizedAccessException异常:“拒绝访问路径“我尝试的任何可能路径(甚至是超出Environment.SpecialFolder范围之外)”。我已经在UWP和Android上尝试访问文件系统,但都遇到了同样的异常。目前为止,我尝试过以下方法,但都没有成功:
  • 通过PCL和DependencyService分别在每个平台上进行操作。
  • 检查文件夹是否为只读。
  • 以管理员权限启动Visual Studio。
  • 将调试模式更改为发布模式。
  • 尝试使用Xam.Plugins.DownloadManager。

  • 代码示例:
    var webClient = new WebClient();
    webClient.DownloadDataCompleted += (s, e) => {
       var bytes = e.Result;
       string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
       string localFilename = "downloaded.jpg";
       string localPath = Path.Combine(documentsPath, localFilename);
       File.WriteAllBytes(localPath, bytes);
    };
    webClient.DownloadDataAsync(new Uri(url));
    

    你的应用程序在每个平台上都有必要的权限吗? - Fabulous
    什么??我怎么可能在Visual Studio 2017中做到那个?我可以为Android设置所需的权限,但这并没有帮助。我不知道如何获得这些权限。 - Bibipkins
    看一下@BrunoCaceiro的答案,它解决了同样的问题,看看它是否能解决你的问题。 - Fabulous
    3个回答

    4
    你面临的是权限问题。
    首先,你需要在AndroidManifest中添加以下内容:
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    自 Android Marshmallow 开始,您需要向用户请求权限,因此我建议使用包Permissions.Plugin
    并在您的 MainActivity 中添加:
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    

    您可以在运行时通过以下方式检查是否具有权限:

    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
        if (status != PermissionStatus.Granted)
        {
            if(await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
            {
                await DisplayAlert("Need storage, "Request storage permission", "OK");
            }
    
            var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
            //Best practice to always check that the key exists
            if(results.ContainsKey(Permission.Storage))
                status = results[Permission.Storage];
        }
    

    如需进一步了解 Android 权限,请查看此博客文章,其中详细解释了所有权限 - https://devblogs.microsoft.com/xamarin/requesting-runtime-permissions-in-android-marshmallow/


    2

    除了Bruno Caceiro的接受的答案之外,您需要声明的UWP权限如下:DocumentsLibrary用于文档,MusicLibrary用于音乐文件夹等。

    您可以通过右键单击项目->属性,然后单击“包清单”,转到功能选项卡(如屏幕截图所示)以图形方式访问这些内容;或者选择查看代码以编辑XML并右键单击package.appxmanifest 。请参见代码摘录以了解如何声明权限。某些对话框中没有表示。

    <Capabilities>
        <Capability Name="internetClient" />
        <uap:Capability Name="documentsLibrary"/>
        <uap:Capability Name="picturesLibrary" />
    </Capabilities>
    

    编辑 另外,您还可以使用 rescap(受限功能)命名空间来添加 <rescap:Capability Name="broadFileSystemAccess" /> 以访问一些受限制的文件夹,从而获取用户有权访问的任何文件/文件夹。

    Capabilities designer


    谢谢!在看到你的回答之前,我花了很多时间让它工作。但是我只能将文件保存到“KnownFolders.SavedPictures”中。现在我可以在任何“KnownFolders”中保存。 - Bibipkins

    1

    我在安卓上遇到了同样的问题,后来意识到问题是因为

    1. 我需要在运行时请求权限,记住你需要同时获得ACCESS_COARSE_LOCATIONWRITE_EXTERNAL_STORAGE权限。

    2. 我使用了错误的路径,我的主要问题是以编程方式获取路径,我无法解决它,所以我通过手动输入路径来解决它。我相信如果你使用正确的完整路径(例如storage/emulated/0/),你不会遇到任何问题。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接