📋

pdfjs-distで日本語の文字が表示されない問題の解決方法

2023/11/25に公開

CDNを使う方法

以下のようにCDNからcMapを読み込むことで表示されるようになります。

pdf-utils.ts
import * as pdfjs from "pdfjs-dist";

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.js",
  import.meta.url,
).toString();

export async function loadPDF(path: string): Promise<pdfjs.PDFPageProxy[]> {  
  const loadingTask = pdfjs.getDocument({
    url: path,
+   cMapUrl: `https://unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,
+   cMapPacked: true,
  });
  const pdf = await loadingTask.promise;
  const pages = [];
  for (let i = 0; i < pdf.numPages; i++) {
    pages.push(await pdf.getPage(i + 1));
  }
  return pages;
}

静的アセットを読み込む方法

あるいはビルドする前にnode_modulesからコピーして使う方法も考えられます。

package.json
{
  "name": "hoge",
  "license": "UNLICENSED",
  "version": "1.0.0",
  "private": true,
  "scripts": {
+   "dev": "copy-cmaps && next dev",
+   "build": "copy-cmaps && next build",
    "start": "next start",
    "lint": "next lint",
    "lint:fix": "next lint --fix",
    "type-check": "tsc --noEmit",
+   "copy-cmaps": "cp -r node_modules/pdfjs-dist/cmaps/ public/cmaps/"

Next.jsなどの場合は public/ 配下に静的アセットとして保存して参照します。

pdf-utils.ts
import * as pdfjs from "pdfjs-dist";

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.js",
  import.meta.url,
).toString();

export async function loadPDF(path: string): Promise<pdfjs.PDFPageProxy[]> {  
  const loadingTask = pdfjs.getDocument({
    url: path,
+   cMapUrl: `/cmaps/`,
+   cMapPacked: true,
  });
  const pdf = await loadingTask.promise;
  const pages = [];
  for (let i = 0; i < pdf.numPages; i++) {
    pages.push(await pdf.getPage(i + 1));
  }
  return pages;
}

Discussion