选择 Xamarin Forms 中存储文件的路径

问题描述 投票:0回答:3

我有一个 Xamarin 表单应用程序,我想保存文件,当用户在手机中打开文件管理器或手机连接到计算机时,应该显示该文件。我读了这篇文章,但问题是文件存储到

Environment.SpecialFolder.Personal
,用户无法打开这个路径。我还发现了这个plugin,它的作用完全相同。它将文件存储到路径
Environment.SpecialFolder.Personal
。当我尝试将文件保存在另一个位置时,我总是收到错误消息:

访问路径“..”被拒绝

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

c# xamarin.forms
3个回答
5
投票

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" />

5
投票

以下是为 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);
    }
}

0
投票

对于 Android,@David Moškoř 的答案非常有效。

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

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

但是必须在IOS项目的

LSSupportsOpeningDocumentsInPlace
文件中启用
Supports Document Browser
Info.plist
才能让用户浏览保存的文件(当您打开
Files
应用程序并导航到
On My iPhone
时会出现)

更新

在较新版本的IOS中,路径应该是:

Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

在 info.plist 中:

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

<key>UISupportsDocumentBrowser</key>
<true/>

<key>UIFileSharingEnabled</key>
<true/>
© www.soinside.com 2019 - 2024. All rights reserved.