【问题标题】:How to Launch a PDF from a UWP (Universal Windows Platform) Web Application如何从 UWP(通用 Windows 平台)Web 应用程序启动 PDF
【发布时间】:2018-02-04 14:42:06
【问题描述】:

我已将现有的 Web 应用程序(HTML5、JS、CSS 等)转换为 Windows UWP 应用程序,以便(希望)我可以通过 Windows 应用商店将其分发到 Surface Hub,以便它可以脱机运行。一切正常,除了 PDF 查看。如果我在新窗口中打开 PDF,基于 Edge 的浏览器窗口就会崩溃。如果我打开一个 IFRAME 并将 PDFJS 加载到其中,那也会崩溃。我真正想做的只是将 PDF 交给操作系统,这样用户就可以在他们安装的任何 PDF 查看器中查看它。

我发现了一些看起来很有希望的特定于 Windows 的 Javascript API,但我无法让它们工作。例如:

 Windows.System.Launcher.launchUriAsync(
   new Windows.Foundation.Uri(
     "file:///"+
     Windows.ApplicationModel.Package.current.installedLocation.path
       .replace(/\//g,"/")+"/app/"+url)).then(function(success) {
                if (!success) {

这会生成一个 file:// URL,我可以将其复制到 Edge 中并显示 PDF,因此我知道 URL 内容是正确的。但是,在应用程序中它什么也不做。

如果我将 https:// URL 传递给该 launchUriAsync 函数,则可以。因此,该函数似乎不喜欢 file:// URL。

我也试过这个:

Windows.ApplicationModel.Package.current.installedLocation.getFileAsync(url).then(
  function(file) { Windows.System.Launcher.launchFileAsync(file) })

那也没用。再次,没有错误。它只是没有做任何事情。

我可以尝试其他的任何想法吗?

-- 更新--

查看接受的答案。这是我最终使用的代码。 (请注意,我所有的文件都在一个名为“app”的子文件夹中):

if (location.href.match(/^ms-appx:/)) {
        url = url.replace(/\?.+/, "");
        Windows.ApplicationModel.Package.current.installedLocation.getFileAsync(("app/" + url).replace(/\//g,"\\")).then(
            function (file) {
                var fn = performance.now()+url.replace(/^.+\./, ".");
                file.copyAsync(Windows.Storage.ApplicationData.current.temporaryFolder,
                    fn).then(
                    function (file2) {
                        Windows.System.Launcher.launchFileAsync(file2)
                    })
            });
        return;
    }

原来你必须把 / 变成 \ 否则它不会找到文件。并且 copyAsync 拒绝覆盖,所以我只使用 performance.now 来确保我总是使用新的文件名。 (在我的应用程序中,PDF 的源文件名无论如何都是自动生成的。)如果你想保留文件名,你必须添加一堆代码来检查它是否已经存在,等等。

【问题讨论】:

    标签: javascript windows pdf uwp


    【解决方案1】:

    LaunchFileAsync 是在这里使用的正确 API。您不能直接从安装目录启动文件,因为它受到保护。您需要先将其复制到其他应用程序可访问的位置(例如您的 PDF 查看器)。使用 StorageFile.CopyAsync 在所需位置制作副本。

    官方SDK示例:https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/AssociationLaunching

    【讨论】:

    • 该 C# 示例中的此注释告诉您:“无法直接从安装文件夹启动文件,因此请先将其复制到临时文件夹”。我会看看我是否能弄清楚如何在 javascript 网络应用程序中进行复制。
    • 正确,需要从安装位置复制。您可以为此使用 StorageFile.CopyAsync。我将编辑我的答案以捕捉该细节。
    • 我将更新我的问题以显示我最终使用的代码。
    【解决方案2】:

    我只是想在这个答案上添加一个变体,它将上面的一些细节与this info 结合起来,将 blob 作为文件保存在 JavaScript 应用程序中。我的情况是我有一个代表 epub 文件数据的 BLOB,并且由于 UWP 内容安全策略,不可能简单地强制单击从 BLOB 创建的 URL(该“简单”方法被明确阻止在 UWP 中,即使它在 Edge 中工作)。这是对我有用的代码:

    // Copy BLOB to downloads folder and launch from there in Edge
    // First create an empty file in the folder
    Windows.Storage.DownloadsFolder.createFileAsync(filename,
        Windows.Storage.CreationCollisionOption.generateUniqueName).then(
        function (file) {
        // Open the returned dummy file in order to copy the data to it 
        file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (output) {
            // Get the InputStream stream from the blob object 
            var input = blob.msDetachStream();
            // Copy the stream from the blob to the File stream 
            Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output).then(
            function () {
                output.flushAsync().done(function () {
                    input.close();
                    output.close();
                    Windows.System.Launcher.launchFileAsync(file);
                });
            });
        });
    }); 
    

    请注意,CreationCollisionOption.generateUniqueName 会自动处理文件重命名,所以我不需要像上面的答案那样摆弄performance.now()

    只是补充一点,UWP 应用开发(尤其是在 JavaScript 中)非常困难的一件事就是很难找到连贯的信息。我花了好几个小时从 sn-ps 整理以上内容并发布回复,遵循错误的路径和不完整的 MS 文档。

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 理想情况下,我想在用户安装的任何 PDF 查看器中启动它。这就是我在基于 Electron 的应用程序中所做的,并且效果很好。获得 PDF 后,他们可以查看、打印、发送电子邮件、将其保存在应用程序之外的某个位置。在我的移动应用程序中也有同样的交易。我只是把它扔给 iOS 上的 QuickLook,或者扔给他们在 Android 上拥有的任何 PDF 查看器。如果无法启动文件,编写一大堆代码来呈现 PDF 可能是一种后备方案。但是为什么不能启动文件呢?这有点疯狂。
      猜你喜欢
      • 1970-01-01
      • 2019-08-06
      • 2016-06-03
      • 2021-05-20
      • 2016-04-25
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      相关资源
      最近更新 更多