TL;DR
- npmで
pdfjs-dist
をインストールして使ったら失敗した。 - 公式サイトからstable版をダウンロードして来たら成功した。
pdfjs
pdfjsの説明は、本家gitのページをgoogle先生の翻訳を参照します。
PDF.jsはHTML5で構築されたPortable Document Format(PDF)ビューアです。
PDF.jsはコミュニティ主導型であり、Mozilla Labsによってサポートされています。私たちの目標は、PDFを解析してレンダリングするための汎用のWeb標準ベースのプラットフォームを作成することです。
PDFを表示しようとした場合、PDFを読み込んでghostscriptで画像に変換して画像を表示してもいいのですが、勉強も兼ねてPDF.jsを使用して表示できないか試しました。
npmでpdfjs-distをインストール
「npm pdfjs」で検索すると、2018/5/29時点では先頭にpdfjs-distがきて、次にpdfjsが来ています。
それぞれのページを開いてrepositoryを確認すると、pdfjs-distがmozilla公式のようです。
実際、pdf.jsのgitのページの中にも、NPMとBowerにはpdfjs-distという名前で登録されている旨の記載があります。
というわけでpdfjs-distと、TypeScriptで使いたいので@types/pdfjs-distを合わせてインストール。
$ npm install --save pdfjs-dist @types/pdfjs-dist
今回インストールされたのは、
- pdfjs-dist@2.0.489
- @types/pdfjs-dist@0.1.2
バージョンに開きがあるのが非常に気になりますが、@types/pdfjs-distのnpmのサイトを確認したところ、何年も更新が止まっているわけではないみたいなので、とりあえず使ってみます。
pdfjs-distを使う
試行錯誤1
なにも考えずに使ってみます。
import { PDFJS } from "pdfjs-dist";
PDFJS.getDocument( "hoge.pdf" )
.then( ( pdfDoc: PDFDocumentProxy ) => {
...
} );
結果は以下の通り。
Uncaught TypeError: Cannot read property 'getDocument' of undefined
なんでやねーん、というわけでこの書き方では失敗しました。
それにしても関連記事、少ないです...皆さんあまりpdfjs-distとTypeScriptの組み合わせは使わないのかな。
試行錯誤2
修正版はこちら。
import { PDFDocumentProxy, PDFJSStatic } from "pdfjs-dist";
const PDFJS: PDFJSStatic = require( "pdfjs-dist" );
PDFJS.getDocument( "hoge.pdf" )
.then( ( pdfDoc: PDFDocumentProxy ) => {
...
} );
これは動きました。
よしよし。
しかし、実際にhtmlから呼び出してみると、コンソールにはWarningが表示されてしまいました。
Warning: Error during font loading: The CMap "baseUrl" parameter must be specified, ensure that the "cMapUrl" and "cMapPacked" API parameters are provided.
表示されたPDFと、Acrobatで表示したPDFを見比べると、文字が表示されていません。
とりあえず、cMapUrlとcMapPackedを確認するように言われているので確認します。
cMapUrlはcmapsのディレクトリまでのパスを指定します。
cmapsは、node_modules/pdfjs-dist/cmaps
を指定しました。
cMapPackedは、cmapの拡張子がbcmapだったらtrueのようです。
import { PDFDocumentProxy, PDFJSStatic } from "pdfjs-dist";
const PDFJS: PDFJSStatic = require( "pdfjs-dist" );
PDFJS.cMapUrl = "パスを入力";
PDFJS.cMapPacked = true;
PDFJS.getDocument( "hoge.pdf" )
.then( ( pdfDoc: PDFDocumentProxy ) => {
...
} );
結果やいかに。
Warning: Error during font loading: The CMap "baseUrl" parameter must be specified, ensure that the "cMapUrl" and "cMapPacked" API parameters are provided.
えぇぇ...。
Chromeの開発者ツールで中身をのぞいてみますが、原因特定できず。
途中まではcMapUrlに値が入っているのに、いざcMapUrlを使っている部分ではundefinedになっているという。
誰かわかる人、教えてください...。
試行錯誤3
npmを使ったインストールにこだわるのはやめました。
公式サイトからstable版をダウンロードして来て、pdf.jsをhtmlで指定することにします。
DLしたzipファイルを解凍して、必要ファイル(cmaps/、pdf.js、pdf.worker.js)をコピーして以下のような構成にします。
cmaps/
index.html
index.js
pdf.js
pdf.worker.js
htmlにscriptタグを追加。
...
<script src="./pdf.js"></script>
...
ts側で読み込み。
const PDFJS: PDFJSStatic = (window as any).PDFJS;
PDFJS.cMapUrl = "cmaps/";
PDFJS.cMapPacked = true;
はい、動きました。
うーん。
pdfjs-distがなぜ動かなかったのかわからない。
PDFを表示するTypeScriptのコード
今回の用途としてはサムネイル表示したかっただけなので、コードとしては先頭ページの表示のみです。
ページ遷移とかは考慮していません。
const PDFJS: PDFJSStatic = (window as any).PDFJS;
PDFJS.cMapUrl = "cmaps/";
PDFJS.cMapPacked = true;
async renderThumbnail(
canvas: HTMLCanvasElement,
size: SizeType,
buff: ArrayBuffer
): Promise<any> {
const pdfDoc = await PDFJS.getDocument( new Uint8Array( buff ) );
const page = await pdfDoc.getPage( 1 );
let viewport = page.getViewport( 1, 0 );
const larger = viewport.height > viewport.width ? viewport.height : viewport.width;
const scale = size / larger;
const rotate = 0;
viewport = page.getViewport( scale, rotate );
const ctx = canvas.getContext( "2d" )!;
const renderContext: PDFRenderParams = {
canvasContext: ctx,
viewport: viewport
};
canvas.height = viewport.height;
canvas.width = viewport.width;
this.setStyle( {
width: viewport.width + "px",
height: viewport.height + "px"
} );
page.render( renderContext );
}