How do you hand over files to the user?

Viewed 110

in a #WASM / #UNO-platform project, how do you hand over files to the user?

In my case I’m generation locally a PDF and had to download it or display it in the browser.

Any clue?
Regards, Michael

1 Answers

There's no API to do that directly, yet. But you can create a data: url on an anchor (a) HTML element.

For this you'll need to create some JavaScript. Here's how you can do it:

IMPORTANT: following code will only work with very recent version of Uno.UI. Version starting with v3.0.0-dev.949+

Create a ContentControl for the <a> tag

[HtmlElement("a")]
public partial class WasmDownload : ContentControl
{
    public static readonly DependencyProperty MimeTypeProperty = DependencyProperty.Register(
        "MimeType", typeof(string), typeof(WasmDownload), new PropertyMetadata("application/octet-stream", OnChanged));

    public string MimeType
    {
        get => (string) GetValue(MimeTypeProperty);
        set => SetValue(MimeTypeProperty, value);
    }

    public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register(
        "FileName", typeof(string), typeof(WasmDownload), new PropertyMetadata("filename.bin", OnChanged));

    public string FileName
    {
        get => (string) GetValue(FileNameProperty);
        set => SetValue(FileNameProperty, value);
    }

    private Memory<byte> _content;

    public void SetContent(Memory<byte> content)
    {
        _content = content;
        Update();
    }

    private static void OnChanged(DependencyObject dependencyobject, DependencyPropertyChangedEventArgs args)
    {
        if (dependencyobject is WasmDownload wd)
        {
            wd.Update();
        }
    }

    private void Update()
    {
        if (_content.Length == 0)
        {
            this.ClearHtmlAttribute("href");
        }
        else
        {
            var base64 = Convert.ToBase64String(_content.ToArray());
            var dataUrl = $"data:{MimeType};base64,{base64}";
            this.SetHtmlAttribute("href", dataUrl);
            this.SetHtmlAttribute("download", FileName);
        }
    }
}

Use it in Your XAML Page

<myControls:WasmDownload FileName="test.txt" x:Name="download">
    Click here to download
</myControls:WasmDownload>

Note you can put anything in the content of your control, as any other XAML ContentControl.

Set the File Content in Code Behind

Loaded += (sender, e) =>
{
    download.MimeType = "text/plain";

    var bytes = Encoding.UTF8.GetBytes("this is the content");
    download.SetContent(bytes);
};

Result

Download Link

Save Dialog

File Opened

Direct support by Uno

There is a PR #3380 to add this feature to Uno natively for all platforms. You can also wait for it instead of doing custom way.

The PR for FileSavePicker has been merged and the feature is now available in package Uno.UI since version 3.0.0-dev.1353.

Related