| File: FilePicker\FilePicker.shared.cs | Web Access |
| Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials) |
#nullable enable using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.Maui.Devices; using Microsoft.Maui.Storage; namespace Microsoft.Maui.Storage { /// <summary> /// Lets the user pick a file from the device's storage. /// </summary> /// <remarks>To enable iCloud capabilities in the file picker on iOS, you'll need to add the iCloud Documents in your <c>Entitlements.plist</c>.</remarks> public interface IFilePicker { /// <summary> /// Opens the default file picker to allow the user to pick a single file. /// </summary> /// <param name="options">File picker options to use; may be <see langword="null"/> for default options.</param> /// <returns>File picking result object, or <see langword="null"/> if picking was cancelled by the user.</returns> /// <remarks> /// File types can be specified in order to limit files that can be selected, using a /// <see cref="PickOptions"/> object. Note that this method may re-throw platform specific exceptions that /// occurred during file picking. When calling <see cref="PickAsync(PickOptions?)"/> again while showing a file /// picker, the <see cref="Task"/> object that was returned from the first call is cancelled. Be sure to /// also handle the <see cref="TaskCanceledException"/> in this case. /// </remarks> Task<FileResult?> PickAsync(PickOptions? options = null); /// <summary> /// Opens the default file picker to allow the user to pick one or more files. /// </summary> /// <param name="options">File picker options to use; may be <see langword="null"/> for default options.</param> /// <returns>An IEnumerable of file picking result objects, or <see langword="null"/> if picking was cancelled by the user.</returns> /// <remarks> /// File types can be specified in order to limit files that can be selected, using a /// <see cref="PickOptions"/> object. Note that this method may re-throw platform specific exceptions that /// occurred during file picking. When calling <see cref="PickMultipleAsync(PickOptions?)"/> again while showing a file /// picker, the <see cref="Task"/> object that was returned from the first call is cancelled. Be sure to /// also handle the <see cref="TaskCanceledException"/> in this case. /// </remarks> Task<IEnumerable<FileResult>> PickMultipleAsync(PickOptions? options = null); } /// <summary> /// Lets the user pick a file from the device's storage. /// </summary> /// <remarks>To enable iCloud capabilities in the file picker on iOS, you'll need to add the iCloud Documents in your <c>Entitlements.plist</c>.</remarks> public static partial class FilePicker { /// <summary> /// Opens the default file picker to allow the user to pick a single file. /// </summary> /// <param name="options">File picker options to use; may be <see langword="null"/> for default options.</param> /// <returns>File picking result object, or <see langword="null"/> if picking was cancelled by the user.</returns> /// <remarks> /// File types can be specified in order to limit files that can be selected, using a /// <see cref="PickOptions"/> object. Note that this method may re-throw platform specific exceptions that /// occurred during file picking. When calling <see cref="PickAsync(PickOptions?)"/> again while showing a file /// picker, the <see cref="Task"/> object that was returned from the first call is cancelled. Be sure to /// also handle the <see cref="TaskCanceledException"/> in this case. /// </remarks> public static Task<FileResult?> PickAsync(PickOptions? options = null) => Default.PickAsync(options); /// <summary> /// Opens the default file picker to allow the user to pick one or more files. /// </summary> /// <param name="options">File picker options to use; may be <see langword="null"/> for default options.</param> /// <returns>An IEnumerable of file picking result objects, or <see langword="null"/> if picking was cancelled by the user.</returns> /// <remarks> /// File types can be specified in order to limit files that can be selected, using a /// <see cref="PickOptions"/> object. Note that this method may re-throw platform specific exceptions that /// occurred during file picking. When calling <see cref="PickMultipleAsync(PickOptions?)"/> again while showing a file /// picker, the <see cref="Task"/> object that was returned from the first call is cancelled. Be sure to /// also handle the <see cref="TaskCanceledException"/> in this case. /// </remarks> public static Task<IEnumerable<FileResult>> PickMultipleAsync(PickOptions? options = null) => Default.PickMultipleAsync(options); static IFilePicker? defaultImplementation; /// <summary> /// Provides the default implementation for static usage of this API. /// </summary> public static IFilePicker Default => defaultImplementation ??= new FilePickerImplementation(); internal static void SetDefault(IFilePicker? implementation) => defaultImplementation = implementation; } partial class FilePickerImplementation : IFilePicker { public async Task<FileResult?> PickAsync(PickOptions? options = null) => (await PlatformPickAsync(options))?.FirstOrDefault(); public Task<IEnumerable<FileResult>> PickMultipleAsync(PickOptions? options = null) => PlatformPickAsync(options ?? PickOptions.Default, true); } /// <summary> /// Represents the file types that are allowed to be picked by the user when using <see cref="IFilePicker"/>. /// </summary> public partial class FilePickerFileType { /// <summary> /// Predefined <see cref="FilePickerFileType"/> object for allowing picking image files only. /// </summary> public static readonly FilePickerFileType Images = PlatformImageFileType(); /// <summary> /// Predefined <see cref="FilePickerFileType"/> object for allowing picking PNG image files only. /// </summary> public static readonly FilePickerFileType Png = PlatformPngFileType(); /// <summary> /// Predefined <see cref="FilePickerFileType"/> object for allowing picking JPEG image files only. /// </summary> public static readonly FilePickerFileType Jpeg = PlatformJpegFileType(); /// <summary> /// Predefined <see cref="FilePickerFileType"/> object for allowing picking video files only. /// </summary> public static readonly FilePickerFileType Videos = PlatformVideoFileType(); /// <summary> /// Predefined <see cref="FilePickerFileType"/> object for allowing picking PDF files only. /// </summary> public static readonly FilePickerFileType Pdf = PlatformPdfFileType(); readonly IDictionary<DevicePlatform, IEnumerable<string>> fileTypes; /// <summary> /// Initializes a new instance of the <see cref="FilePickerFileType"/> class. /// </summary> protected FilePickerFileType() => fileTypes = new Dictionary<DevicePlatform, IEnumerable<string>>(); /// <summary> /// Initializes a new instance of the <see cref="FilePickerFileType"/> class. /// </summary> /// <param name="fileTypes"> /// A <see cref="IDictionary{TKey, TValue}"/> where the key is the platform /// and the value is a collection of file types that are allowed to be picked by the user. /// </param> /// <remarks>Note that the file types (specified in the <paramref name="fileTypes"/> value) /// should be identified differently per platform.</remarks> public FilePickerFileType(IDictionary<DevicePlatform, IEnumerable<string>> fileTypes) => this.fileTypes = fileTypes; /// <summary> /// Gets the configured allowed file types that can be picked by the user for the current platform. /// </summary> /// <exception cref="PlatformNotSupportedException">Thrown if the current platform does not have any file types configured.</exception> public IEnumerable<string> Value => GetPlatformFileType(DeviceInfo.Current.Platform); /// <summary> /// Gets the configured allowed file types that can be picked by the user for the current platform. /// </summary> /// <exception cref="PlatformNotSupportedException">Thrown if the current platform does not have any file types configured.</exception> protected virtual IEnumerable<string> GetPlatformFileType(DevicePlatform platform) { if (fileTypes.TryGetValue(platform, out var type)) return type; throw new PlatformNotSupportedException("This platform does not support this file type."); } } /// <summary> /// Represents file picking options that can be used to customize the working of <see cref="IFilePicker"/>. /// </summary> public class PickOptions { /// <summary> /// Default file picking options. This object can be used when no special pick options are necessary. /// </summary> public static PickOptions Default => new PickOptions { FileTypes = null, }; /// <summary> /// Predefined <see cref="PickOptions"/> object for picking image files only. /// </summary> public static PickOptions Images => new PickOptions { FileTypes = FilePickerFileType.Images }; /// <summary> /// Title used for the file picker that is shown to the user. /// </summary> /// <remarks>The file picker title is only used on the Android platform and only for certain file pickers. This title is not guaranteed to be shown.</remarks> public string? PickerTitle { get; set; } /// <summary> /// List of file types that file file picker should return. /// </summary> /// <remarks> /// On Android and iOS the files not matching this list are shown in the file picker, /// but will be grayed out and cannot be selected. /// When the <see cref="FilePickerFileType.Value"/> array is <see langword="null"/> or empty, /// all file types can be selected while picking. /// The contents of this array is platform specific; every platform has its own way to /// specify the file types. /// <para>On Android you can specify one or more MIME types, e.g. /// <c>image/png</c>. Additionally, wildcard characters can be used, e.g. <c>image/*</c></para> /// <para>On iOS, you can specify <c>UTType</c> constants, e.g. <c>UTType.Image</c>.</para> /// <para>On Windows, you can specify a list of extensions, like this: <c>".jpg", ".png"</c>.</para> ///</remarks> public FilePickerFileType? FileTypes { get; set; } } }