You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI3应用中WebView2结合PDF.js无法渲染PDF问题排查

问题原因
  1. 应用沙箱权限限制:打包后的WinUI3应用运行在系统受限沙箱中,以ms-appx-web://协议加载的WebView2页面,无法通过file:///协议直接访问本地文件系统中的文件——这是UWP/WinUI3的安全机制,防止应用未经授权访问用户文件。
  2. 路径格式错误:你构造的本地文件URL存在格式问题,Windows路径的盘符后需用/分隔,但示例中生成的URL是C%3A%2MyTest(正确应为C:/MyTest),转义错误导致路径无法被PDF.js识别。
解决方案

推荐两种可靠的解决方法,根据你的场景选择:

方法一:通过WebView2虚拟主机映射访问文件

适合需要保留文件原存储位置的场景,将PDF文件所在目录映射为WebView2可访问的虚拟主机:

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();

        // 映射PDF.js资源目录到虚拟主机
        var pdfjsPath = Path.Combine(AppContext.BaseDirectory, "Assets", "pdfjs");
        PdfWebView.CoreWebView2.SetVirtualHostNameToFolderMapping(
            "appassets", pdfjsPath, CoreWebView2HostResourceAccessKind.Allow);

        // 映射PDF文件所在的父目录到虚拟主机
        var pdfParentFolder = Path.GetDirectoryName(file.Path);
        PdfWebView.CoreWebView2.SetVirtualHostNameToFolderMapping(
            "pdfhost", pdfParentFolder, CoreWebView2HostResourceAccessKind.Allow);

        // 构造虚拟主机下的PDF文件URL
        var fileName = Path.GetFileName(file.Path);
        var pdfVirtualUrl = $"https://pdfhost/{Uri.EscapeDataString(fileName)}";

        // 使用虚拟主机URL加载PDF.js viewer,并传递PDF地址
        var pdfjsViewerUri = "https://appassets/web/viewer.html";
        PdfWebView.Source = new Uri($"{pdfjsViewerUri}?file={Uri.EscapeDataString(pdfVirtualUrl)}");
    }
}

注意点

  • 虚拟主机必须使用https://协议(WebView2强制要求)
  • 同时通过虚拟主机访问PDF.js的viewer.html,避免跨源访问被拦截

方法二:将PDF转为Base64数据URL加载

适合小体积PDF文件,直接读取文件内容转为Base64格式,通过data: URL传递给PDF.js:

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);

        // 读取PDF文件并转为Base64数据URL
        var fileBytes = await File.ReadAllBytesAsync(file.Path);
        var base64Pdf = Convert.ToBase64String(fileBytes);
        var dataUrl = $"data:application/pdf;base64,{base64Pdf}";

        var pdfjsViewerUri = "https://appassets/web/viewer.html";
        PdfWebView.Source = new Uri($"{pdfjsViewerUri}?file={Uri.EscapeDataString(dataUrl)}");
    }
}
额外注意事项
  • 确保PDF.js的viewer.html允许加载自定义来源的文件:默认PDF.js可能会限制文件来源,可修改viewer.js中的ALLOWED_FILE_ORIGINS配置,添加虚拟主机域名或允许所有来源(仅测试环境使用)
  • 打包应用时,将Assets/pdfjs目录下的所有文件设置为“复制到输出目录”(在Visual Studio中右键文件→属性→复制到输出目录→选择“始终复制”)

内容的提问来源于stack exchange,提问作者Ogaili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:40:56