.NET MAUI Documentation

Microsoft Developer Network

Uploading Files in .NET MAUI

This tutorial guides you through implementing file upload functionality in your .NET MAUI applications. We'll cover how to select files and send them to a server.

Introduction

.NET MAUI enables you to build cross-platform native applications for Windows, macOS, iOS, and Android from a single codebase. File uploading is a common requirement in many applications, allowing users to share data, submit forms, or upload media.

Prerequisites

  • .NET 6 or later installed.
  • Visual Studio 2022 with the .NET MAUI workload.
  • A basic understanding of C# and .NET MAUI development.
  • A backend service to receive file uploads (e.g., ASP.NET Core Web API).

Steps to Implement File Upload

1. File Selection

You'll need a way for users to select files from their device. .NET MAUI doesn't have a built-in file picker control, but you can use community libraries or platform-specific implementations.

A popular and recommended approach is to use the CommunityToolkit.Maui.MauiExtensions library, which provides a convenient FilePickerService.

Installing the NuGet Package

dotnet add package CommunityToolkit.Maui.MauiExtensions

Using the File Picker Service

In your MAUI application's MauiProgram.cs, register the service:

using CommunityToolkit.Maui.Markup;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFamily("OpenSans-Regular.ttf");
                fonts.AddFamily("OpenSans-Semibold.ttf");
            })
            .Services.AddSingleton<IFilePickerService, FilePickerService>();

        return builder.Build();
    }
}

Then, inject the service into your ViewModel or Page and use it to pick a file:

using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Models;

// In your ViewModel or Page
public class UploadViewModel : ObservableObject
{
    private readonly IFilePickerService _filePickerService;

    [ObservableProperty]
    private string selectedFileName;

    public UploadViewModel(IFilePickerService filePickerService)
    {
        _filePickerService = filePickerService;
    }

    [RelayCommand]
    public async Task PickFileAsync()
    {
        var result = await _filePickerService.PickFileAsync();
        if (result != null)
        {
            SelectedFileName = $"Selected: {result.FileName}";
            // You'll need to store the file stream or path for uploading
        }
    }
}

2. Uploading the File

Once you have the selected file's stream or path, you can upload it to your server using HttpClient.

Example UI for File Upload

In your XAML:

<!-- In your ContentPage.xaml -->
<StackLayout Padding="20" Spacing="10">
    <Button Text="Select File" Command="{Binding PickFileCommand}" />
    <Label Text="{Binding SelectedFileName}" />
    <Button Text="Upload File" Command="{Binding UploadFileCommand}" />
    <!-- Optional: Progress Bar -->
    <StackLayout x:Name="progressBarContainer" IsVisible="False">
        <ProgressBar Progress="{Binding UploadProgress}" />
        <Label Text="{Binding UploadProgressText}" />
    </StackLayout>
</StackLayout>

Uploading Logic in ViewModel

Extend your ViewModel to handle the upload:

using System.Net.Http;
using System.IO;
using System.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Maui.Models;
using System.Threading.Tasks;

public partial class UploadViewModel : ObservableObject
{
    // ... existing properties and constructor ...

    [ObservableProperty] private double uploadProgress;
    [ObservableProperty] private string uploadProgressText;

    [RelayCommand]
    public async Task UploadFileAsync()
    {
        if (PickedFile == null) return;

        var httpClient = new HttpClient();
        var url = "YOUR_SERVER_UPLOAD_URL"; // e.g., "https://yourserver.com/api/upload"

        using (var formData = new MultipartFormDataContent())
        {
            var fileContent = new StreamContent(PickedFile.GetStream());
            fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
                {
                Name = "file"; // The name of the form field
                FileName = PickedFile.FileName;
            }

            formData.Add(fileContent, "file", PickedFile.FileName);

            try
            {
                UploadProgressText = "Uploading...";
                var response = await httpClient.PostAsync(url, formData, new CancellationToken());

                if (response.IsSuccessStatusCode)
                {
                    SelectedFileName = "Upload successful!";
                    UploadProgress = 1.0;
                    UploadProgressText = "";
                }
                else
                {
                    SelectedFileName = $"Upload failed: {response.StatusCode}";
                    UploadProgress = 0;
                    UploadProgressText = "";
                }
            }
            catch (Exception ex)
            {
                SelectedFileName = $"Error: {ex.Message}";
                UploadProgress = 0;
                UploadProgressText = "";
            }
        }
    }
}

3. Handling Progress (Optional)

For larger files, it's good practice to show upload progress. You can achieve this by creating a custom StreamContent that reports progress.

Tip: For detailed progress reporting, consider using a custom StreamContent implementation that wraps the file stream and reports bytes sent.

4. Backend Considerations

Your server-side application (e.g., ASP.NET Core Web API) needs to be configured to accept file uploads. This typically involves:

  • Creating an API endpoint that accepts POST requests.
  • Using IFormFile to bind the uploaded file.
  • Saving the file to a designated directory on the server.
  • Handling potential errors like large file sizes or invalid file types.

Example ASP.NET Core Web API Controller Action

using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;

[Route("api/[controller]")]
[ApiController]
public class UploadController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> UploadFile(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("No file uploaded.");

        var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "Uploads");
        if (!Directory.Exists(uploadsFolder))
            Directory.CreateDirectory(uploadsFolder);

        var filePath = Path.Combine(uploadsFolder, file.FileName);

        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }

        return Ok(new { message = $"File '{file.FileName}' uploaded successfully." });
    }
}

Conclusion

By following these steps, you can effectively implement file upload functionality in your .NET MAUI applications, enhancing user interaction and data sharing capabilities.

Remember to replace YOUR_SERVER_UPLOAD_URL with the actual URL of your backend upload endpoint.

For more advanced scenarios, such as handling multiple files, resuming interrupted uploads, or implementing security measures, explore the capabilities of your chosen backend framework and consider specialized libraries.