Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
571 views
in Technique[技术] by (71.8m points)

javascript - How to Launch a PDF from a UWP (Universal Windows Platform) Web Application

I've converted an existing web application (HTML5, JS, CSS, etc.) into a Windows UWP app so that (hopefully) I can distribute it via the Windows Store to Surface Hubs so it can run offline. Everything is working fine, except PDF viewing. If I open a PDF in a new window, the Edge-based browser window simply crashes. If I open an IFRAME and load PDFJS into it, that also crashes. What I'd really like to do is just hand off the PDF to the operating system so the user can view it in whatever PDF viewer they have installed.

I've found some windows-specific Javascript APIs that seem promising, but I cannot get them to work. For example:

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

That generates a file:// URL that I can copy into Edge and it shows the PDF, so I know the URL stuff is right. However, in the application it does nothing.

If I pass an https:// URL into that launchUriAsync function, that works. So it appears that function just doesn't like file:// URLs.

I also tried this:

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

That didn't work either. Again, no error. It just didn't do anything.

Any ideas of other things I could try?

-- Update --

See the accepted answer. Here is the code I ended up using. (Note that all my files are in a subfolder called "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;
    }

Turns out you have to turn the / into or it won't find the file. And copyAsync refuses to overwrite, so I just use performance.now to ensure I always use a new file name. (In my application, the source file names of the PDFs are auto-generated anyway.) If you wanted to keep the filename, you'd have to add a bunch of code to check whether it's already there, etc.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

LaunchFileAsync is the right API to use here. You can't launch a file directly from the install directory because it is protected. You need to copy it first to a location that is accessible for the other app (e.g. your PDF viewer). Use StorageFile.CopyAsync to make a copy in the desired location.

Official SDK sample: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/AssociationLaunching


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...