The FileOpenPicker works on UWP, but not on any other platform.
The FileOpenPicker works an all platforms - (at least all expect WASM as this might be more complicated see #35)
Simply make a call to the FileOpenPicker from Windows.Storage.Pickers.
Affected platform(s):
Greetings, any news on this?
howdy @mfe-, we would accept a pull-request that implements this, even if it was a partial implementation for a single platform. I have set aside time to pair with folks like yourself to help with contributing features to the code base. Let me know if you are keen.
Hi @ghuntley I'm afraid I don't know much about mono wasm and how the Uno platform works. As I'm still interested in this topic, I'm reading into it and let you know when I'm ready.
After gathering pieces on the internet, here is something that is almost working for wasm:
function openFilePicker() {
var input = document.createElement('input');
input.type = 'file';
input.accept = '.jpg, .png, .jpeg, .gif, .bmp, .tif, .tiff|image/*';
input.onchange = e => {
var file = e.target.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = readerEvent => {
var content = readerEvent.target.result; // this is the content!var content = readerEvent.target.result; // this is the content!
var selectFile = Module.mono_bind_static_method("[MyApp.Wasm] MyApp.Shared.MyPage:SelectFile");
selectFile (content);
};
};
input.click();
}
private async void OnLogoButtonClicked(object sender, RoutedEventArgs e)
{
MyPage.FileSelectedEvent -= OnFileSelectedEvent;
MyPage.FileSelectedEvent += OnFileSelectedEvent;
WebAssemblyRuntime.InvokeJS("openFilePicker();");
}
public static void SelectFile(string imageAsDataUrl) => FileSelectedEvent?.Invoke(null, new FileSelectedEventHandlerArgs(imageAsDataUrl));
private void OnFileSelectedEvent(object sender, FileSelectedEventHandlerArgs e)
{
MyPage.FileSelectedEvent -= OnFileSelectedEvent;
var base64Data = Regex.Match(e.FileAsDataUrl, @"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
((IMyPageViewModel) DataContext).ImageBytes= binData;
}
private static event FileSelectedEventHandler FileSelectedEvent;
private delegate void FileSelectedEventHandler(object sender, FileSelectedEventHandlerArgs args);
private class FileSelectedEventHandlerArgs
{
public string FileAsDataUrl { get; }
public FileSelectedEventHandlerArgs(string fileAsDataUrl) => FileAsDataUrl = fileAsDataUrl;
}
Note: it's easier to directly set the html image src:
var image = document.getElementsByTagName("img")[0];
image.src = content;
The problem is that we need a mecanism to identify the correct image. Some tag that would be set in xaml and pass trough to html for example.
Here we go 馃槃
function openFilePicker(htmlId) {
console.log(htmlId);
var input = document.createElement('input');
input.type = 'file';
input.accept = '.jpg, .png, .jpeg, .gif, .bmp, .tif, .tiff|image/*';
input.onchange = e => {
var file = e.target.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = readerEvent => {
var content = readerEvent.target.result; // this is the content!
var imageDiv = document.getElementById(htmlId);
var image = imageDiv.getElementsByTagName('img')[0];
image.src = content;
var selectFile = Module.mono_bind_static_method("[MyApp.Wasm] MyApp.Shared.MyPage:SelectFile");
selectFile (content);
};
};
input.click();
}
WebAssemblyRuntime.InvokeJS($"openFilePicker({MyImage.HtmlId});");
Is there a way to upvote this without creating more comments/items?
It is implemented for Android, but not included in Uno. You have to make your own compilation, adding #2896.
Created separate issue for macOS implementation #3890.
There is a Native File System API which is implemented in Chromium browsers, and can be enabled via a flag, though the W3C spec is still marked as a Draft. Mozilla seems to be working on the spec as well (see here).
For early adopters, it could be worth adding FileOpenPicker support via this API. When the Native File System API is finalized, should the API interfaces change, they can be updated in Uno.
edit: Looking into it further, "Original trial" means you need to request a token from Google to use the API before it's ready. The token is locked to a specific origin, has a usage limit, and the entire feature will be disabled (e.g. they outright remove the flag) if used by more than 0.5% of all Chrome page loads. So it won't be feasible to add this for everyone in WASM right now.
Most helpful comment
Here we go 馃槃