Ogaili
Ogaili

Reputation: 11

Not Rendering PDF in WebView

I'm trying to display a PDF file in my packaged WinUI3 application using PDF.js and WebView2, but I'm encountering an issue where the PDF doesn't render, and I get a "File not found" error within the WebView2 control.

private async void PickAFileButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
    var window = App.MainWindow;
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
    WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);
    openPicker.ViewMode = PickerViewMode.Thumbnail;
    openPicker.FileTypeFilter.Add(".pdf");

    var file = await openPicker.PickSingleFileAsync();

    if (file != null)
    {
        await PdfWebView.EnsureCoreWebView2Async();

        var pdfjsPath = Path.Combine(AppContext.BaseDirectory, "Assets", "pdfjs");
        PdfWebView.CoreWebView2.SetVirtualHostNameToFolderMapping(
            "appassets", pdfjsPath,CoreWebView2HostResourceAccessKind.Allow);

        var pdfFilePath = new Uri($"file:///{file.Path}");

        var pdfjsViewerUri = "ms-appx-web:///Assets/pdfjs/web/viewer.html";
        var encodedFilePath = Uri.EscapeDataString(pdfFilePath.AbsoluteUri);
        PdfWebView.Source = new Uri($"{pdfjsViewerUri}?file={encodedFilePath}");
    }
}

WebView2 Source: ms-appx-web:///Assets/pdfjs/web/viewer.html?file=file%3A%2F%2F%2FC%3A%2MyTest%2F2024%2F07%2F01%2Ffolder%2520test%2Ffiles%2520and%2520pdf%2F300.pdf

Any ideas on why the PDF is not rendering and how to fix this issue?

Upvotes: 1

Views: 122

Answers (2)

jerry
jerry

Reputation: 333

I did try to use webview2 to render PDF with following sample code. You need to read the local file into byte[] array.

  private void ShowPDFInWebView2(byte[] data)
    {
        string htmTemplate = @"<!DOCTYPE html><html><head><meta charset='UTF-8'><style>
            html, body {
              height: 100%;
              margin: 0;
              padding: 0;
            }
            .embed-container {
              height: 100%;
            }
            .embed-container embed {
              width: 100%;
              height: 100%;
            }
        </style></head>" +
        "<body><div class='embed-container'><embed src='#srccontent#' type='application/pdf' /></div></body></html>";

        htmTemplate = htmTemplate.Replace("#srccontent#", "data:application/pdf;base64," + Convert.ToBase64String(data));
        pdfViewer2.NavigateToString(htmTemplate);
    }

Upvotes: 0

David Risney
David Risney

Reputation: 4387

To load local content in WebView2 you have a number of options which are discussed in the linked doc:

Scenario file URL HTML string virtual host name map WebResourceRequested
Origin-based DOM APIs ✔️ ✔️ ✔️
DOM APIs requiring secure context ✔️ ✔️
Dynamic content ✔️ ✔️
Additional web resources ✔️ ✔️ ✔️
Additional web resources resolved in WebView2 process ✔️ ✔️

In your case you are attempting to use ms-appx-web which is a URI scheme supported by the previous WebView control but not by WebView2. The closest WebView2 supported mechanism is the virtual host name mapping.

You are already setting up that mapping so you need to use it instead of ms-appx-web:

        PdfWebView.Source = new Uri($"https://appassets/web/viewer.html?file={encodedFilePath}");

Upvotes: 0

Related Questions