ストアアプリ内ではPDFを表示できない?!
こんにちは。中山です。
ストアアプリからPDFファイルを表示したいなぁという場合、通常は
- 外部のビューアアプリ(標準の「リーダー」アプリなど)を起動して、そちらのアプリでPDFファイルを表示する。
という方法がまず考えられます。
たいていの場合は、これで解決するのですが、ときには、どうしても、アプリ内で独自にPDFを制御したい(拡大・縮小表示、ページ送り、手描き編集などなど)、というシチュエーションが出てくるかもしれません。
しかし、ここでひとつ問題が出てきます。
Windowsストアアプリの標準SDKでは、PDFを操作するための機能が提供されていないのです。
(※2013/10/29追記: Windows8.1からは、ストアアプリ内でPDFを表示するためのAPIが提供されているようですね。)
やはり、ストアアプリ内部でPDFを表示する、ということは難しいのか・・・。
ほとんどあきらめかけていたそのとき、ある方法で、この問題を解決できることがわかったのでした。
サードパーティ製のライブラリもあるが・・・
実は、以下のようなサードパーティ製のライブラリもいくつか提供されており、これらを用いることで、Windowsストアアプリ内でのPDFファイル表示というのは実現可能です。
しかし、これらはいずれも「有料」のライブラリなのです。
したがって、気軽にちょっと試してみる、というわけにいかないのがつらいところです。
やはり「お金」で解決するしかないのかも・・・、と思っていたときに見つけたのが、これ。
Mozillaが提供している、
というライブラリです。
「pdf.js」とは
pdf.jsとは、Mozillaが開発している、HTML5ベースのPDFビューアです。
このpdf.jsを用いることで、ブラウザ上でPDFファイルをレンダリングして表示する、ということが可能になります。
この仕組み、どこかで見たことあるなぁと思ったら、最近のバージョンのFirefoxブラウザでPDFを開こうととしたときに、ブラウザ内に表示されるアレが、この「pdf.js」でした。
pdf.jsを、ストアアプリに組み込んでみる
ここでひとつひらめきました。
- pdf.jsをストアアプリ内に組み込んで、そのストアアプリのウェブビューで表示するようにすれば、「アプリ内でのPDF表示」というのが実現できてしまうのではないか!?
幸いなことに、pdf.jsは、Apacheバージョン2.0ライセンスのオープンソースとして提供されているため、利用する上でも問題なさそうです。
さっそく作業にとりかかりました。
その結果、できたのがこれです。
表示のパフォーマンスも、なんとか実用レベルにはなっていると思われます。
さらに、「アプリ内でPDFファイルが表示できること」の利点を示すために、手描き機能も実装してみました。
(エラー処理など、機能的に不完全なところもあるかもしれませんが、ご容赦ください。)
ウェブビューを通じて、という形ではありますが、ストアアプリ内でのPDFファイル表示を実現することができました。
このサンプルアプリのソースコードは、こちらからダウンロードすることができます。
(なお、こちらのソースコードを使用、または第三者に提供することによって生じた、いかなる損害に対しても、一切責任を負いません。ご了承ください。)
実装のポイント
実装するにあたり、いちばんのネックとなったのが、ウェブビューで表示するHTMLコンテンツの配置場所です。
「pdf.js」ライブラリは、PDFレンダリングを担当する「pdf.js」ファイルのほかにも、「viewer.html」「viewer.js」など、いくつかのHTMLファイル、JavaScriptファイルなどから構成されています。
ストアアプリの場合、こういったファイルを格納するのは、プロジェクト内の「Assets」フォルダです。
しかし、この「Assets」フォルダに配置したままでは、正しくPDFファイルを表示することができませんでした。
ストアアプリのウェブビューから「Assets」フォルダのファイルにアクセスするには、
ms-appx-web:///Assets/web/viewer.html
という独自のプロトコルのURLを用いる必要があります。しかしながらこのようなURLは、「pdf.js」ライブラリ側では、うまく取り扱えないようでした。
これを解決するために、
- アプリ内で独自のHTTPサーバを稼働
- Assetsフォルダ内のファイル(HTML、JavaScriptなどのファイル)を、アプリのローカルデータフォルダ(=「ApplicationData.Current.LocalFolder」でアクセスできるフォルダ)にコピー
- アプリ内HTTPサーバを経由して、そのローカルデータフォルダにコピーしたファイルにアクセス
という方法をとりました。
独自のHTTPサーバを稼働させることで、
http://localhost:8088/web/viewer.html
といった形で、通常のhttpプロトコルでコンテンツにアクセスすることが可能となり、「pdf.js」ライブラリの機能も、問題なく動作するようになりました。
この独自のHTTPサーバに関する部分は、ソースコード内にある「HttpServer」クラスが担当しています。
なお、画面起動時に任意のPDFファイルを表示するには、
http://localhost:8088/web/viewer.html?file=/pdf/mysample.pdf
というふうに、URLの「file」パラメータに、表示対象のPDFファイルのパスを指定します。
この場合、対象のPDFファイルは、同じドメインのドキュメントルート内に配置しておく必要があります。
(他のサイトのPDFファイルのパスを、「file」パラメータに指定して表示することはできません。)