狛ログ

2020年10月29日木曜日

Node.jsを使用して、S3上のPDFをマージする方法。


オフィス狛 技術部のmmm(むー)です。

先日、業務でPDFのマージ作業が必要でしたので、その備忘録を残します。
マージ作業には、pdf-libというライブラリを使用しました。

pdf-libとは
pdf-libとは、PDFを作成・マージするためのnpmパッケージです。
今回はNode.jsで作業を行いましたが、ブラウザ側のJavaScriptでも使用することができます。また、PDFのマージだけではなく、実際にコードベースでPDFの作成もできるようです。
参考:https://www.npmjs.com/package/pdf-lib (公式)

【前提条件】
Nodeとnpmがインストールされていること。

1. pdf-libのインストール

使用したいプロジェクト配下に移動し、下記を実行します。
$ cd ~/<プロジェクトパス>
$ npm install --save pdf-lib

package.json に下記が追加されました。
// package.json

"dependencies": {
    "pdf-lib": "^1.11.1",
  }

2. S3からファイルを読み込む

< ... > 内は可変ですので、ご自身の環境の値を設定してください。
   const aws = require('aws-sdk');

// S3にアクセスするための情報
const s3Client = new aws.S3({
  accessKeyId: <accessKeyId>,
  secretAccessKey: <secretAccessKey>,
  region: <region>,
});

// バケットの情報 
// (バケット内にディレクトリを作成していない場合は、Keyにファイル名のみ指定してください)
const params = {
      Bucket: <bucketName>,
      Key: <s3DirectoryName>/<file.pdf>,
    };

// S3にある対象ファイル情報取得
const dataInS3 = await s3Client.getObject(params).promise();

// bufferデータを取得
const bufferData = dataInS3.Body;

// 💡 S3ではなく実行環境上にファイルがある場合は、下記のみでファイルの情報を取得できます
const fs = require('fs');
const file1 = await PDFDocument.load(fs.readFileSync('./file1.pdf'));


3. 読み込んだPDFをマージする

本来であれば複数のPDFをS3から読み込むと思いますが、今回は同じPDFファイルでマージします。
const fs = require('fs');
const { PDFDocument } = require('pdf-lib');

// マージ用の空PDF空を作成
const mergedPdf = await PDFDocument.create();

// マージ対象のファイル情報取得
const targetPdf = await PDFDocument.load(bufferData);

// マージ対象のファイルの全てのページ情報取得
const targetPdfPages = await mergedPdf.copyPages(
  targetPdf,
  targetPdf.getPageIndices(),
);

// 最初に作成した空のマージ用PDFに、マージ対象の全てのページを追加
for (const page of targetPdfPages) {
  mergedPdf.addPage(page);
}

// 💡 1ページだけ取得したい場合はこちら (下記例は、最初の1ページのみ取得)
const [targetPdfOnePage] = await mergedPdf.copyPages(
  targetPdf,
  [0],
);

// マージ用PDFに、1ページ更に追加
mergedPdf.addPage(targetPdfOnePage);

4. マージしたファイルを書き出す

ディレクトリを指定してファイルを書き出す場合、ディレクトリが存在しないとエラーになるので注意してください。
// PDFファイル書き出し
fs.writeFileSync('./merge.pdf', await mergedPdf.save());

5. マージしたファイルをレスポンスする

下記コードは、Expressを使用しています。
const pdfBytes = await mergedPdf.save();
const pdfbuffer = Buffer.from(pdfBytes);

res
    .attachment('merge.pdf')
    .set('Content-Type', 'application/pdf')
    .set('isBase64Encoded', true)
    .send(pdfBuffer)
    .toString('base64');

以上となります。
PDFをマージする必要がある場合、参考にしてみてください🍭

, ,

0 件のコメント:

コメントを投稿