【问题标题】:Select path for storing file in Xamarin Forms选择在 Xamarin Forms 中存储文件的路径
【发布时间】:2018-01-29 22:37:40
【问题描述】:

我有一个 Xamarin 表单应用程序,我想保存文件,当用户在他的手机中打开文件管理器或手机连接到计算机时,应该显示该文件。我读了这个article,但问题是文件存储到Environment.SpecialFolder.Personal,用户无法打开这个路径。我还发现了这个plugin,它做的事情完全一样。它将文件存储到路径Environment.SpecialFolder.Personal。当我尝试将文件保存在另一个位置时,我总是收到错误消息:

对路径“..”的访问被拒绝

我应该使用哪个路径来保存文件?

【问题讨论】:

  • 你想把文件保存在哪里?到下载文件夹?
  • 要下载文件夹或任何其他文件夹,我只希望用户在使用文件管理器或将手机连接到计算机时可以看到该文件。

标签: c# xamarin.forms


【解决方案1】:

System.Environment.SpecialFolder.Personal 类型映射到路径 /data/data/[your.package.name]/files。这是您的应用程序的私有目录,因此除非具有 root 权限,否则您将无法使用文件浏览器查看这些文件。

所以如果你想让文件被用户找到,你不能将文件保存在Personal文件夹中,而是在另一个文件夹中(例如Downloads):

string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, "yourfile.txt");

您还必须为AndroidManifest.xml添加权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

【讨论】:

  • 好答案。但是如何获取ios中下载文件夹的路径呢?
  • 你把这段代码放在哪里?如果添加到主页面,会报错“Android在当前上下文中不存在”如果添加到xamarin的android部分,那么如何从主页面调用呢?
【解决方案2】:

这是为 Android、iOS 和 UWP 保存图像的代码:

安卓:

public void SaveImage(string filepath)
{
    var imageData = System.IO.File.ReadAllBytes(filepath);
    var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(
    Android.OS.Environment.DirectoryDcim);
    var pictures = dir.AbsolutePath;
    var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
    var newFilepath = System.IO.Path.Combine(pictures, filename);

    System.IO.File.WriteAllBytes(newFilepath, imageData);
    //mediascan adds the saved image into the gallery
    var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
    mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(newFilepath)));
    Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
}

iOS:

public async void SaveImage(string filepath)
{
    // First, check to see if we have initially asked the user for permission 
    // to access their photo album.
    if (Photos.PHPhotoLibrary.AuthorizationStatus == 
        Photos.PHAuthorizationStatus.NotDetermined)
    {
        var status = 
            await Plugin.Permissions.CrossPermissions.Current.RequestPermissionsAsync(
                Plugin.Permissions.Abstractions.Permission.Photos);
    }
    
    if (Photos.PHPhotoLibrary.AuthorizationStatus == 
        Photos.PHAuthorizationStatus.Authorized)
    {
        // We have permission to access their photo album, 
        // so we can go ahead and save the image.
        var imageData = System.IO.File.ReadAllBytes(filepath);
        var myImage = new UIImage(NSData.FromArray(imageData));

        myImage.SaveToPhotosAlbum((image, error) =>
        {
            if (error != null)
                System.Diagnostics.Debug.WriteLine(error.ToString());
        });
    }
}

请注意,对于 iOS,我使用 Plugin.Permissions nuget 数据包向用户请求权限。

UWP:

public async void SaveImage(string filepath)
{
    var imageData = System.IO.File.ReadAllBytes(filepath);
    var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
    
    if (Device.Idiom == TargetIdiom.Desktop)
    {
        var savePicker = new Windows.Storage.Pickers.FileSavePicker();
        savePicker.SuggestedStartLocation = 
            Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
        savePicker.SuggestedFileName = filename;
        savePicker.FileTypeChoices.Add("JPEG Image", new List<string>() { ".jpg" });

        var file = await savePicker.PickSaveFileAsync();

        if (file != null)
        {
            CachedFileManager.DeferUpdates(file);
            await FileIO.WriteBytesAsync(file, imageData);
            var status = await CachedFileManager.CompleteUpdatesAsync(file);

            if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
                System.Diagnostics.Debug.WriteLine("Saved successfully"));
        }
    }
    else
    {
        StorageFolder storageFolder = KnownFolders.SavedPictures;
        StorageFile sampleFile = await storageFolder.CreateFileAsync(
            filename + ".jpg", CreationCollisionOption.ReplaceExisting);
        await FileIO.WriteBytesAsync(sampleFile, imageData);
    }
}

【讨论】:

    【解决方案3】:

    对于 Android,@David Moškoř 的答案完美运行。

    对于IOS,我们可以使用如下路径:

    Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library"); 
    

    但是LSSupportsOpeningDocumentsInPlaceSupports Document Browser必须在IOS项目的Info.plist文件中启用才能让用户浏览保存的文件(当你打开Files应用程序并导航到On My iPhone时会出现)

    【讨论】:

      猜你喜欢
      • 2021-02-17
      • 2022-11-18
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 2019-11-08
      相关资源
      最近更新 更多