Working with files in .NET MAUI

Serhii Korol - Jun 15 '23 - - Dev Community

In this article, I would like to talk about files on mobile devices. We'll create files, open them in a file explorer, and filter by type. Let's go.

Above all, let's create a simple MAUI project:

dotnet new maui -n FilePickAndSaveSample
Enter fullscreen mode Exit fullscreen mode

Let's go to the "MainPage.xaml” file and delete all elements in VerticalStackLayout block. It's no need us. In "MainePage.xaml.cs” file, the same delete redutant code and leave only constructor.
Following step, you need to install the "CommunityToolkit.Maui” package. After you'll do it, you should register it. For this go to the "MauiProgram.cs” and add this code:

var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseMauiCommunityToolkit()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
Enter fullscreen mode Exit fullscreen mode

Next, let's make saving files to our mobile device. Lets back to our "MainPage.xaml” file and add a couple items: button and label.

<Label
    HorizontalOptions="Center"
    HorizontalTextAlignment="Center"
    LineBreakMode="WordWrap"
    Text="The FileSaver provides the ability to select target     folder and save files to the file system." />

<Button
    Clicked="SaveFile_Clicked"
    HorizontalOptions="Center"
    Text="Save file" />
Enter fullscreen mode Exit fullscreen mode

And then go to the "MainPage.xaml.cs” file and create two handlers:

private async void SaveFile_Clicked(object sender, EventArgs e)
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken cancellationToken = cancellationTokenSource.Token;

        try
        {
            await SaveFile(cancellationToken);
        }
        catch (OperationCanceledException)
        {
            throw new OperationCanceledException("It was cancelled");
        }
    }
Enter fullscreen mode Exit fullscreen mode

And also let's create a separate method for save files:

private async Task SaveFile(CancellationToken cancellationToken)
    {
        using var stream = new MemoryStream(Encoding.Default.GetBytes("Hello from the Dev.to Community!"));
        var fileName = Application.Current?.MainPage?.DisplayPromptAsync("FileSaver", "Choose filename") ?? Task.FromResult("untitled.txt");
        var fileSaverResult = await FileSaver.Default.SaveAsync(await fileName, stream, cancellationToken);
        if (fileSaverResult.IsSuccessful)
        {
            await Toast.Make($"The file was saved successfully to location: {fileSaverResult.FilePath}").Show(cancellationToken);
        }
        else
        {
            await Toast.Make($"The file was not saved successfully with error: {fileSaverResult.Exception.Message}").Show(cancellationToken);
        }
    }
Enter fullscreen mode Exit fullscreen mode

But it's not all. Let's go back to the "MauiProgram.cs” file and register service, just add this row:

builder.Services.AddSingleton(FileSaver.Default);
Enter fullscreen mode Exit fullscreen mode

By the way. How you might have noticed we injected service FileSaver statical way, but you can use another two ways: inject to constructor or create new instance. For convenient, I'll use static injecting.

But anyway let's check out.

Stage 1: main

Click to the "Save TXT” button:

Stage 1: type name

Type "plain_text.txt” and tap OK. Further, choose local storage and move into it. Repeat the same procedure for “doc_text.doc” and "pic.jpeg”

And now, lets create service for pick folder. It's everything similiar with save file. First, go to the "MauiProgram.cs” file and register new service:

builder.Services.AddSingleton(FolderPicker.Default);
Enter fullscreen mode Exit fullscreen mode

And also add lable and button:

<Label
    HorizontalOptions="Center"
    HorizontalTextAlignment="Center"
    LineBreakMode="WordWrap"
    Text="FolderPicker allows you to pick a folder from the  device" />

<Button
    Clicked="PickFolder_Clicked"
    HorizontalOptions="Center"
    Text="Pick Folder" />
Enter fullscreen mode Exit fullscreen mode

Also it needs handler and method:

private async void PickFolder_Clicked(object sender, EventArgs e)
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken cancellationToken = cancellationTokenSource.Token;

        try
        {
            await PickFolder(cancellationToken);
        }
        catch (OperationCanceledException)
        {
            throw new OperationCanceledException("It was cancelled");
        }
    }

    private async Task PickFolder(CancellationToken cancellationToken)
    {
        var folderResult = await FolderPicker.PickAsync("DCIM", cancellationToken);
        if (folderResult.IsSuccessful)
        {
            var filesCount = Directory.EnumerateFiles(folderResult.Folder.Path).Count();
            await Toast.Make($"Folder picked: Name - {folderResult.Folder.Name}, Path - {folderResult.Folder.Path}, Files count - {filesCount}", ToastDuration.Long).Show(cancellationToken);
        }
        else
        {
            await Toast.Make($"Folder is not picked, {folderResult.Exception.Message}").Show(cancellationToken);
        }
    }
Enter fullscreen mode Exit fullscreen mode

Lets check out:

Stage 2: main

Click on the "Pick Folder” and select folder. If tap to button again, you'll be at the same folder that you selected earlier.

Stage 2: selected folder

And last thing that I wanted to show, it's pick file by type. Lets to do it and register service:

builder.Services.AddSingleton(FilePicker.Default);
Enter fullscreen mode Exit fullscreen mode

Add the lable and the couple of buttons:

<Label
    HorizontalOptions="Center"
    HorizontalTextAlignment="Center"
    LineBreakMode="WordWrap"
    Text="FilePicker allows you to pick a file from the device" />

<Button
    Clicked="PickPhoto_Clicked"
    HorizontalOptions="Center"
    Text="Pick a Photo" />

<Button
    Clicked="PickFile_Clicked"
    HorizontalOptions="Center"
    Text="Pick a File" />

<Label
    FontSize="15"
    HorizontalTextAlignment="Center"
    x:Name="FileName" />
Enter fullscreen mode Exit fullscreen mode

Add handlers:

private async void PickPhoto_Clicked(object sender, EventArgs e)
    {
        FileResult result = await _filePicker.PickAsync(new PickOptions
        {
            PickerTitle = "Pick a Photo",
            FileTypes = FilePickerFileType.Images
        });

        if (result == null) return;

        FileName.Text = result.FileName;
    }

    private async void PickFile_Clicked(object sender, EventArgs e)
    {
        var customFileTypes = new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>>
        {
            {
                DevicePlatform.iOS, new[]
                {

                    "com.microsoft.word.doc",
                    "public.plain-text",
                    "org.openxmlformats.wordprocessingml.document"
                }
            },
            {
                DevicePlatform.Android, new[]
                {
                    "application/msword",
                    "text-plain",
                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                }
            },
            {
                DevicePlatform.WinUI, new[]
                {
                    "doc","docx", "txt"
                }
            },
        });

        FileResult result = await _filePicker.PickAsync(new PickOptions
        {
            PickerTitle = "Pick a File",
            FileTypes = customFileTypes
        });

        if (result == null) return;

        FileName.Text = result.FileName;
    }
Enter fullscreen mode Exit fullscreen mode

And now we can check out. If you click "Pick a Photo”, you can choose only pictures.

Stage 3: main

Stage 3: filtered file

Thats all. Source: CLICK

Happy coding!

Buy Me A Beer

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .