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