FileMakerでフル機能のPDFビューアを作る

以前、Office文書をWebビューアに表示する方法を紹介しましたが、今回は別の方法でPDF文書を(操作パネル付きで)FileMaker内に表示します。


beezwax

Full-Featured PDF Viewer Embedded in FileMaker

(元記事はこちら)

Christopher Edwards
2018/4/2

JavaScript PDFビューアをFileMakerに統合する – JavaScriptコーディングは不要

最近、PDF文書管理の機能を持ったアプリケーションを作成しました。それはオブジェクトフィールドを使っただけの単純なものに見えるかもしれませんが、コンテンツ管理システム(CMS)レベルの機能でクライアントを満足させたいと考えました。今回はFileMakerに高機能なPDFビューアを直接組み込んだ方法を紹介します。

開発サイクル1: オブジェクトフィールド

FileMakerは、標準機能であるオブジェクトフィールドを利用して、バイナリデータを直接保存することができます。一つの優れた機能として、データをデータベース自体の内部に格納するか、またはホストのファイルシステムに格納するかを選択することができます。PDFを外部に保存することは、ディスクスペースの節約、パフォーマンスの向上、ホスト管理者が柔軟に別のパーティションまたはドライブを使用できることなど、多くの利点があります。

そこで我々はインポートするデータ用のテーブルを作成し、PDFを保持するためのオブジェクトフィールドを追加し、外部保存に設定しました。これで完成かというと…

まだ続きがあります。

デフォルトでは、オブジェクトフィールドは画像などの静的コンテンツ用に設定されます。ユーザがPDFをインポートしようとすると、PDFオプションはグレー表示され、一般的なファイルを挿入するように強制されます。オブジェクトフィールドを表示すると、ファイルのアイコン([挿入]-[ファイル]の場合)、または最初のページの画像だけ(ドラッグ&ドロップの場合)が表示されます。一応動作はしますが、ユーザ体験的にはあまりよくありません。

 

 

 

PDFの場合は、必ずインスペクタの「データ」タブに移動して、オブジェクトフィールドをインタラクティブコンテンツに最適化してください。これによってユーザは”PDFを挿入”メニューオプションを選択でき、常に最初のページのサムネイルが表示されるようになるので、ユーザ体験は向上します。

 

 

 

 

さらに良いこととして、ユーザはPDFを操作できるようになります。具体的には、ページ間のスクロール、表示オプションの変更、ズームとサイズ変更が可能になります。PDFをダウンロードする手順はまだ直感的ではなく、わざわざメニューから[編集]-[フィールド内容をエクスポート]を選択する必要がありますが、少なくともコントロール+クリックで、プレビューから開くことができます。

プレビューには、PDFの操作性を向上させる優れた機能がいくつかありますが、我々はFileMakerの開発者であり、元々利用できるはずの機能のために外部プログラムに頼りたくはありません。

そこで、WebビューアとMozillaのPDF.jsライブラリの出番です。

開発サイクル2: Webビューア

オブジェクトフィールドにPDFを表示する代わりに、ファイルをエクスポートしてWebビューアに表示するとどうなるでしょうか?

この単純なプロセスによって、Safariと同じようなホバーコントロールが可能になります。これは、WebビューアがSafariエンジンを利用しているからです。

このコントロールを使って、簡単なズーム、プレビューで開く、ダウンロードが可能になります。これらは便利ですが、我々のクライアントが求めていた、検索や目次の参照などの高度な機能はありません。

開発サイクル3: JavaScript

あなたは今、私と同じように、「私はJavaScript開発者じゃないのに」と思っていることでしょう。心配は無用です。JavaScriptは1行も書きません。一方でクライアントへの機能的な恩恵は、わずかな統合の努力に見合うだけのものがあります。

以下では、検索、ハイライト、目次やサムネールの閲覧、ファイルを開く、ダウンロード、印刷などの機能が利用できます。FileMakerの中で、フル機能を備えたPDFビューアが実現します。ここからの私の焦点は、PDFでできることのすべてを紹介することではなく(あなたの活用方法はあなた自身で見つけることができるでしょう)、FileMakerソリューションにこの機能をどう組み込むか、です。

このブログ記事の最後にあるデモファイル(PDFViewerDemo.fmp12)は、Mozillaの無料・オープンソース・ApacheライセンスのPDF.jsライブラリをFileMakerに実装する方法を示しています。

https://mozilla.github.io/pdf.js/

ここでもPDFをオブジェクトフィールドに保存しますが、それをオブジェクトフィールド自体ではなくWebビューアに表示します。

このライブラリをあなた自身のソリューションに移す手順は、以下の5つのステップです。

  1. PDF_JS_ASSETSテーブルをファイルにコピーする
  2. 2つのスクリプトをPDF.jsフォルダにコピーする
  3. Webビューアで簡単なレイアウトを作成する。実際、JavaScriptライブラリがすべての機能を提供するので、パーツはWebビューアだけでOKです。あるいは既存のレイアウトにWebビューアを配置します。どちらにするかは、開発者としてのあなたの自由です。
  4. 既存のPDFビューアのスクリプトに以下の3行を追加する
  5. フィールドPDF_VIEWER_DEMO::SAMPLE_PDF_FILEに値を設定し、Webビューアのオブジェクト名を“pdf_viewer”にする

これで設定完了です。

次に、最適化の方法を見ていきましょう。

開発サイクル4: 最適化

当然ながら、ホストのパフォーマンス、ネットワーク速度、ファイルサイズなど、PDFの表示速度を決定する変動要素はいろいろあります。その上で、我々のテストでは、500 KBのPDFが約10秒で表示され、20 MBのPDFが約1分で表示されました。一応機能はしますが、理想的ではありません。

舞台裏で何が起こっているのか見てみましょう。

  1. スクリプトに追加した3行のうちの1行目は、PDFを元のオブジェクトフィールドから、スクリプトが動作するグローバルコンテナフィールドにコピーします。我々のテストでは、これが表示までの時間の約40%を占めました。
  2. 2行目でスクリプトを呼び出して、3つのことをします。まず、サブスクリプトを呼び出して、PDF.jsライブラリをFileMakerの一時フォルダにエクスポートします。これは、ユーザが初めてPDFを表示したときにのみ発生します。同じセッションでの2回目以降の表示では、ライブラリを再エクスポートする必要はありません。
  3. スクリプトは次に、PDFをBase64エンコードしてグローバルフィールドに挿入します。このエンコードされたテキストをHTMLテンプレートに挿入します。このテンプレートは、JavaScript PDFビューアおよびエンコードされたPDFのラッパーとして機能します。最後に、この組み合わせたHTMLを別のグローバルのオブジェクトフィールドにUTF-8エンコードテキストとして保存します。この部分にも同じく、全体の40%の時間がかかることがわかりました。
  4. 最後に、エンコードされたテキストファイルがFileMakerの一時フォルダにエクスポートされ、そのパスがスクリプトに渡され、スクリプトがWebビューアに表示されます。この部分が残りの20%を占めます。

このサンプルを私たちのソリューションに統合するのはとても簡単でしたが、パフォーマンスが犠牲になりました。明らかにさらなる改善の余地があるので、サンプルコードを特定のアプリケーションにより密接に結合した場合にどうなるかを見てみましょう。

上で説明した基本的なプロセスは同じですが、UTF-8テキストを事前にキャッシュすることで上記の1と3をなくしました。また、上記2をmacOSシェルコマンドにzipファイルの解凍をさせることで、その部分の待ち時間もなくしました。実装の詳細は対象ファイルの構造に依存しますが、以下に私たちが行ったことの概要を示します。

ユーザが最初にPDFをインポートしたときに、それをBase64エンコードしてHTMLテンプレートと結合し、それをUTF-8テキストファイルとして実際のPDFとは別のオブジェクトフィールドに保存しておきます。具体的には以下のようになります:

Set Field [ PDF_VIEWER_DEMO::PDF_ENCODED ;
    Let (
        [
            ~html_template = TextDecode ( PDF_JS_ASSETS::VIEWER_HTML_TEMPLATE ; "UTF-8" ) ;
            ~replacement_tag = “{{[BASE_64_PDF_DATA]}}” ;
            ~base64_data = Base64EncodeRFC ( 3548 ; PDF_VIEWER_DEMO::SAMPLE_PDF_FILE ) ;
            ~template_with_base_64_data = Substitute ( ~html_template ; [ ~replacement_tag ; ~base64_data ] )
        ] ;
        TextEncode ( ~template_with_base_64_data ; "UTF-8" ; 1 )
    )
]

この比較的重い操作をユーザから見えないようにするために、サーバ上でスクリプトを実行(PSoS)を使用できます。これによって処理時間を80%削減し、2つのグローバルフィールドをなくし、コピーした2つのスクリプトのうち1つを既存のスクリプトに埋め込みました。ソリューションにすでに開発者用テーブル(ソリューション全体に関するフィールドを保持する1つのレコードを持つ)がある場合は、2つのオブジェクトフィールドをそのテーブルにコピーすれば、PDF_JS_ASSETSテーブルを追加せずに済みます。

パフォーマンステストを再実行したところ、当初は何らかの問題が発生しているのかと思いました。というのも、ほとんどの場合、PDFが1〜2秒で表示されるようになったからです。

この驚異的なパフォーマンスの向上には、追加の努力に加えて、あなたのソリューション(できればあなたがすでに開発したもの)についての詳細な知識と、そしてこのライブラリを実装する方法の基礎的な理解(それを私がこの記事であなたに与えられたと願っています)の両方が必要です。この努力への投資は、ユーザに最高の体験を提供するために、とても価値があると思います。

デモファイルPDFViewerDemo.fmp12をダウンロード

MozillaUK Film EducationUniversity of FloridaSteve Senft-HerreraAndrew WitschonkeJay GonzalesVince Menannoに感謝します。

Leave a Reply