FlutterでPDF出力してみた!日本語文字化けの解決方法も紹介

目次

はじめに

業務アプリ開発中に、初めてFlutterからPDFを出力する機能を実装しました。
「難しそう…」と思っていたのですが、意外とシンプルにできたので、設定方法とハマったポイントをまとめます。

同じことで悩んでいる方の参考になれば嬉しいです!


使用したパッケージ

dependencies:
  pdf: ^3.11.1
  printing: ^5.13.1
  path_provider: ^2.1.3
  • pdf:PDFファイルを生成するパッケージ
  • printing:生成したPDFを共有・印刷するパッケージ
  • path_provider:ファイルの保存場所を取得するパッケージ

pubspec.yamlに追記したら忘れずに↓を実行します。

flutter pub get

基本的な実装の流れ

PDF出力の流れはシンプルです。

① pw.Documentを作成
② ページとコンテンツを追加
③ pdf.save()でバイト列に変換
④ Printing.sharePdf()で共有シートを表示

PDFを生成するコード

import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';

Future<void> generateAndSharePdf() async {
  final pdf = pw.Document();

  pdf.addPage(
    pw.Page(
      pageFormat: PdfPageFormat.a4,
      build: (context) => pw.Center(
        child: pw.Text('XXXXX'),
      ),
    ),
  );

  final bytes = await pdf.save();

  await Printing.sharePdf(
    bytes: bytes,
    filename: 'XXXXX.pdf',
  );
}

たったこれだけでiOSの共有シートが表示されて、印刷・保存・メール送信ができます!


ハマったポイント:日本語が文字化けする!

問題

いざPDFを出力してみたら…日本語が全部文字化けしていました😱

テーブルのヘッダーも、物件名も、全部「□□□□」のような表示に。

原因

pdfパッケージはデフォルトで日本語フォントを持っていません。
英数字は表示できますが、日本語(ひらがな・カタカナ・漢字)は対応フォントがないと文字化けしてしまいます。

解決方法

NotoSansJPフォントを追加することで解決できました!

① Google FontsからNotoSansJPをダウンロード

https://fonts.google.com/noto/specimen/Noto+Sans+JP

右上の「Get font」からダウンロード→ZIPを解凍→NotoSansJP-Regular.ttfを取り出します。

② フォントファイルをassetsに配置

assets/
└── fonts/
    └── NotoSansJP-Regular.ttf
mkdir -p assets/fonts

③ pubspec.yamlに登録

flutter:
  assets:
    - assets/fonts/

  fonts:
    - family: NotoSansJP
      fonts:
        - asset: assets/fonts/NotoSansJP-Regular.ttf

④ PDFコードでフォントを読み込む

import 'package:flutter/services.dart';

// フォントを読み込む(asyncが必要)
final fontData = await rootBundle
    .load('assets/fonts/NotoSansJP-Regular.ttf');
final ttf = pw.Font.ttf(fontData);

// テキストスタイルにフォントを指定
final style = pw.TextStyle(font: ttf, fontSize: 12);

pdf.addPage(
  pw.Page(
    build: (context) => pw.Text('XXXXX', style: style),
  ),
);

注意点: フォントを読み込む処理がasyncになるので、PDF生成メソッドもFuture<pw.Document>に変更する必要があります。


実際に出力できたPDFは

シミュレーターで試しましたが、PDFの出力からは色々な共有が表示されました。

この中でプレビューを選択すると、PDFの詳細を確認することができます。
また、下の段にあるPrintを選択したところ実際にA4で印刷でき、レイアウトもバッチリでした!!


まとめ

ポイント内容
パッケージpdf + printing + path_provider
PDF生成pw.Documentにページを追加してsave()
共有・印刷Printing.sharePdf()一発でOK
日本語対応NotoSansJPフォントをassetsに追加

日本語対応さえ乗り越えれば、FlutterのPDF出力は思ったより簡単でした!
同じところでハマっている方の参考になれば嬉しいです

目次