Xamarin 表单:如何在设备外部存储中创建文件夹和文件?

Xamarin forms: How to create folder and a file in device external storage?

我正在尝试在设备的外部存储上创建一个文件夹和该文件夹中的一个文本文件。 与 WhatsApp 一样。另外,我需要向该文件写入一些数据。

是否可以在 xamarin 表单中执行此操作?还是我们需要使用依赖服务?

提前致谢

更新

@Lucas Zhang - MSFT 我尝试了你的依赖服务,但设备上没有生成任何文件或文件夹。我无法使用 PCLStorage,因为我需要在设备外部文件夹中创建文件。

这其实不是我要找的。我需要先创建一个文件夹,然后在该文件夹上创建一个文本文件。我需要在不丢失以前数据的情况下将数据写入该文件。该文件和文件夹应该在设备文件管理器上可见,因为该文件将由用户使用。

我觉得界面应该有2个功能。

void CreateFolderAndFile(string folderName,string FileName); //在这个函数上我们需要在设备文件夹上创建一个文件夹和文件如果不是已经存在。如果它已经存在,什么也不做。

void WriteDataToFile(string data); //在这个函数中我们需要将数据写入到上面添加的文件中

do this in xamarin forms? Or should we need to use a dependency service?

选项 1:

当然要用到依赖服务了

在Android项目中

public async Task SaveAndView(string fileName, String contentType, MemoryStream stream)
        {
            try
            {
                string root = null;
                //Get the root path in android device.
                if (Android.OS.Environment.IsExternalStorageEmulated)
                {
                    root = Android.OS.Environment.ExternalStorageDirectory.ToString();
                }
                else
                    root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

                //Create directory and file 
                Java.IO.File myDir = new Java.IO.File(root + "/meusarquivos");
                myDir.Mkdir();

                Java.IO.File file = new Java.IO.File(myDir, fileName);

                //Remove if the file exists
                if (file.Exists()) file.Delete();

                //Write the stream into the file
                FileOutputStream outs = new FileOutputStream(file);
                outs.Write(stream.ToArray());

                outs.Flush();
                outs.Close();
           }
            catch (Exception ex)
            {
                //...
            }
        }
await DependencyService.Get<ISave>().SaveAndView(xxx.ToString() + ".pdf", "application/pdf", stream);

不要忘记添加以下权限并获得运行时权限。

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

在iOS

iOS 对应用程序可以对文件系统执行的操作施加了一些限制,以保护应用程序数据的安全性,并保护用户免受恶意应用程序的侵害。这些限制是应用程序沙箱的一部分——一组限制应用程序访问文件、首选项、网络资源、硬件等的规则。应用程序仅限于在其主目录(安装位置)内读取和写入文件;它无法访问另一个应用程序的文件。

您可以查看 docs 了解更多详情。

选项 2:

如果您确实想直接在 Forms 中实现它。我们可以使用插件 PCLStorage 来自 nuget .

跨平台本地文件夹

在Xamarin.Form中,PCLStorage API将帮助我们检索所有平台的本地文件夹名称和路径,使用下面给出的代码。无需编写任何特定于平台的代码即可访问本地文件夹。

Using PCLStorage;  

IFolder folder = FileSystem.Current.LocalStorage; 

正在创建新文件夹

要在本地文件夹中创建新的子文件夹,请调用 CreateFolderAsync 方法。

string folderName ="xxx" ;  
IFolder folder = FileSystem.Current.LocalStorage;  
folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);  

创建新文件

要在本地文件夹中创建新文件,请调用 CreateFileAsync 方法。

string filename=”username.txt”;  
IFolder folder = FileSystem.Current.LocalStorage;  
IFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);  

检查文件夹是否已经存在

我们可以检查特定文件夹中的现有文件夹,如下所示。

public async static Task<bool> IsFolderExistAsync(this string folderName, IFolder rootFolder = null)  
     {  
         // get hold of the file system  
         IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
         ExistenceCheckResult folderexist = await folder.CheckExistsAsync(folderName);  
         // already run at least once, don't overwrite what's there  
         if (folderexist == ExistenceCheckResult.FolderExists)  
         {  
             return true;  
  
         }  
         return false;  
     }  

检查文件是否已经存在

我们可以检查特定文件夹中的现有文件,如下所示。

public async static Task<bool> IsFileExistAsync(this string fileName, IFolder rootFolder = null)  
        {  
            // get hold of the file system  
            IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
            ExistenceCheckResult folderexist = await folder.CheckExistsAsync(fileName);  
            // already run at least once, don't overwrite what's there  
            if (folderexist == ExistenceCheckResult.FileExists)  
            {  
                return true;  
  
            }  
            return false;  
        }  

写入文件

如果要写入任何扩展文件文档,只需使用 WriteAllTextAsync 方法进行写入即可。

public async static Task<bool> WriteTextAllAsync(this string filename, string content = "", IFolder rootFolder = null)  
      {  
          IFile file = await filename.CreateFile(rootFolder);  
          await file.WriteAllTextAsync(content);  
          return true;  
      }  

注意:您仍然需要在 Android 项目中添加权限。

更新

文件class提供了在共享项目中创建、删除、读取文件的相关方法,但只能访问应用程序文件夹。

File.WriteAllText(fileName, text);
string text = File.ReadAllText(fileName);

要在外部存储中创建文件,请尝试使用DependencyService在原生平台上实​​现该功能。

1.create接口定义方法

public interface IAccessFile
{
    void CreateFile(string FileName);
}

2.implementandroid平台上的服务

[assembly: Xamarin.Forms.Dependency(typeof(AccessFileImplement))]
namespace XamarinFirebase.Droid
{
    public class AccessFileImplement : IAccessFile
    {
        void CreateFile(string FileName)
        {
            string text = "xxx";
            byte[] data = Encoding.ASCII.GetBytes(text);
            string DownloadsPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
            string filePath = Path.Combine(DownloadsPath, FileName);
            File.WriteAllBytes(filePath, data);
        }
    }
}

3.consume共享项目中的DependencyService命令

DependencyService.Get<IAccessFile>().CreateFile("myfile.txt");

它在 iOS 平台上不可用,iOS 对应用程序可以对文件系统执行的操作施加了一些限制,以保护应用程序数据的安全性。 应用程序仅限于在其主目录(安装位置)内读写文件;它无法访问另一个应用程序的文件。

相关教程:

https://docs.microsoft.com/en-us/xamarin/android/platform/files/external-storage?tabs=windows

https://docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/file-system#special-considerations