Search code examples
uwpwinui-3windows-app-sdk

WinUI3 cannot open storage file from Uri


I have just upgraded a UWP app to WinUI3. The absolute majority of code has remained unchanged and the app works, however I have found that the process for downloading and subsequently viewing a file from the internet is now failing.

The method in its entirety is shown below.

It works in UWP but not WinUI3 (presumably Windows App SDK generally). According to the docs, the StorageFile class and related methods should work the same.

 private async void OpenFileClicked(object sender, RoutedEventArgs e)
 {
     try
     {
         int id = (int)((Button)sender).Tag;

         AttachmentTemplate attachment = Attachments.FirstOrDefault(x => x.ID == id);

         if (attachment == null)
             throw new Exception("Attachment not found!");

         StorageFile viewing = await StorageFile.CreateStreamedFileFromUriAsync(
              attachment.FileName + attachment.FileType, 
              new Uri(attachment.WebLocation), 
              null);

         bool success = await Windows.System.Launcher.LaunchFileAsync(viewing);

         if (!success)
             throw new Exception("Could not launch file!");
     }
     catch (Exception ex)
     {
         await Functions.ShowMessageDialog(Functions.ErrorMessage(ex));
     }
 }

The method succeeds but when the file is launched it is shown as corrupted. For example a pdf file will launch the PDF viewer but it notifies me that the PDF is corrupted. Similar for images which open in the photo viewer but it says the image is corrupted.

This leads me to believe the file is not being successfully downloaded, but I don't know why since it works fine with UWP.


Solution

  • This is not strictly a solution but I have found a workaround by manually downloading the file first and handling the byte array afterwards.

    A basic example:

    using(var client = new System.Net.Http.HttpClient())
    {
        var result = await client.GetByteArrayAsync(new Uri("https://www.my-web-location.com/whatever"));
    
        StorageFile viewing = await result.AsStorageFile(fileName);
    
        bool success = await Launcher.LaunchFileAsync(viewing);
    
        if (!success)
            throw new Exception("Could not launch file!");
    
    }
    
    // The method for turning byte array into StorageFile
    public static async Task<StorageFile> AsStorageFile(this byte[] byteArray, string fileName)
    {
        StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
        StorageFile file = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
        
        await FileIO.WriteBytesAsync(file, byteArray);
        
        return file;
    }