Sreejith Sree
Sreejith Sree

Reputation: 3766

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

I am trying to create a folder and a text file in that folder on the device's external storage. The same as WhatsApp does. Also, I need to write some data to that file.

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

Thanks in advance

UPDATE

@Lucas Zhang - MSFT I try your dependency service but no file or folder is generating on the device. I can't use PCLStorage since I need to create the file in device external folder.

This is not actually I am looking for. I need a create a folder first, then a text file on that folder. I need to write data into that file without losing the previous data. That file and folder should be visible on the device file manager because that file is going to use by the users.

I think the interface should have 2 functions.

void CreateFolderAndFile(string folderName,string FileName); //on this function we need to create a folder and file on device folder if it is not already exist. If it already exists do nothing.

void WriteDataToFile(string data); //on this function we need to write the data to the file added on top

Upvotes: 2

Views: 4477

Answers (1)

Lucas Zhang
Lucas Zhang

Reputation: 18861

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

Option 1:

Of course we need to use dependency service .

in Android project

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);

Do not forget to add following permission and achieve runtime permission.

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

in iOS

iOS imposes some restrictions on what an application can do with the file system to preserve the security of an application’s data, and to protect users from malignant apps. These restrictions are part of the Application Sandbox – a set of rules that limits an application’s access to files, preferences, network resources, hardware, etc. An application is limited to reading and writing files within its home directory (installed location); it cannot access another application’s files.

You could check the docs for more details .

Option 2:

If you do want to implement it in Forms directly . We could use the plugin PCLStorage from nuget .

Cross-platform Local Folder

In Xamarin.Form, the PCLStorage API will help us to retrieve all the platforms' local folder names and paths, using the code given below. There is no need to write any platform-specific code to access the local folder.

Using PCLStorage;  

IFolder folder = FileSystem.Current.LocalStorage; 

Creating new folders

To create a new subfolder in the local folder, call the CreateFolderAsync method.

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

Create New file

To create a new file in the local folder, call the CreateFileAsync method.

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

Check Folder Already Exists

We can check for an existing folder in a particular folder, as shown below.

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;  
     }  

Check File Already Exists

We can check for an existing file in a particular folder, as shown below.

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;  
        }  

Write File

If you want to write any extension file document, just use the WriteAllTextAsync method for write.

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;  
      }  

Note: you still need to add permission in Android project .

Update

The File class provides the related method to create, delete, and read files in the shared project, but it can only access the application folder.

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

To create a file in the external storage, try to achieve the function on the native platform using DependencyService.

1.create an interface to define the method

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

2.implement the service on the android platform

[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 the DependencyService command in the shared project

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

It cannot be available on iOS platform, iOS imposes some restrictions on what an application can do with the file system to preserve the security of an application’s data. An application is limited to reading and writing files within its home directory (installed location); it cannot access another application’s files.

Related tutorials:

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

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

Upvotes: 3

Related Questions