見出し画像

pdffontsの自動実行(1)

昨日の朝、白鳥の群れが飛んでいくのを見ました。春ですね。さて、今週はfetchで取得したpdfファイルに対して、pdffontsを実行する部分を実装したいと思います。

対象ファイルのpdffontsの結果を取得

kintoneのRestAPIで処理対象のレコードを複数取得して、各レコードに添付されているpdfのpdffontsの実行結果を対象レコードに反映するとなると、こんな感じの実装ができれば良いかなと思いました。

kintoneに登録されたデータをもとにpdffontsを実行する処理のイメージ
対象レコード分、添付ファイルをダウンロードしてpdffontsを実行

ダウンロードしたpdfのpdffontsの実行

// pdffontsの実行 とコメントを書いたら、GitHub Copilotが以下のコードを提案してくれたので中身を確認します。

 // pdffontsの実行
  runPdffonts = async (resultPath: string, pdfFile: string): Promise<boolean> => {
    const exec = require("child_process").exec;
    const command = `pdffonts ${pdfFile} > ${resultPath}`;
    const promise = new Promise<boolean>((resolve, reject) => {
      exec(command, (error: any) => {
        if (error) {
          reject(error);
        }
        resolve(true);
      });
    });
    return promise;
  }

子プロセスとしてpdffontsを実行して、その結果を対象pdfファイル名に対応したテキストファイルに書き出す関数です。戻り値は正常に実行できた場合にresolve(true)を、エラーの場合はreject(error)をpromiseとして返却します。pdffontsの実行成否で結果を返却するのはイメージできるのですが、rejectとresolveが何を意味するのかを確認します。

コールバック関数のresolveとreject

Promise インスタンスの作成は new Promise(executor) が基本形で、executorはコールバック関数です。executorは引数としてresolve, rejectの2つを受け取ります。上記のコードを見ると、pdffontsの実行成否によりresolveとrejectを受け取っています。「Promise コンストラクタと Executor 関数」を読んでみると、実行に成功した場合にはPromise履行時の値としてtrueを、エラーが発生した場合はPromise拒否時の理由としてエラーを返却するということがわかります。コメントを書くだけで、正しい関数が生成されたわけですね。提案されたコードが正しいかどうか判断できるなら、コーディングの効率が上がりそうです。(私の場合は、使いこなすために、まだまだ精進しなければなりません)関数runPdffontsの結果がtrueだった場合は、kintoneのレコードのpdffonts実行結果カラムにテキストに出力された内容を反映し、レコードのステータスをpdffonts実行済に進めれば良さそうです。エラーの場合は、レコードのpdffonts実行結果カラムもレコードのステータスも変更しないことにします。

子プロセスとしてpdffonts実行を試してみる

正しそうなので、ここまでの実装内容を試してみます。

TypeError: Promise resolver undefined is not a function
    at new Promise (<anonymous>)
    at runPfdfonts (/home/tetrapod/fetchAPItest/fetchPDF/fetchPDF.js:96:21)
    at /home/tetrapod/fetchAPItest/fetchPDF/fetchPDF.js:48:37
    at Array.map (<anonymous>)
    at /home/tetrapod/fetchAPItest/fetchPDF/fetchPDF.js:42:24
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Node.js v18.13.0

あー、resolveとrejectにあたるコールバック関数が無いというエラーが。履行時の関数と、拒否時の関数をthenに記述します。

 // pdffontsの実行
  runPdffonts = async (resultPath: string, pdfFile: string): Promise<boolean> => {
    const exec = require("child_process").exec;
    const command = `pdffonts ${pdfFile} > ${resultPath}`;
    const promise = new Promise<boolean>((resolve, reject) => {
      exec(command, (error: any) => {
        if (error) {
          reject(error);
        }
        resolve(true);
      });
    });
    return promise;
  }).then(
        function resolve(val) {
            console.log(`onFulfilled ${val}`);
        },
        function reject(reason) {
            console.log(`onRejected reason ${reason}`);
        } );
    return promise;
}

改めて、実行してみます。

$ node fetchPDF.js 
SET TOKEN
getRecords 3 records
fetch start README.md contentType:application/octet-stream
fetch start manifest.json contentType:application/json
fetch start Chrome拡張MV3について.pdf contentType:application/pdf
onRejected reason Error: Command failed: pdffonts temp/manifest.json > temp/manifest.json
Syntax Error: Document stream is empty

onRejected reason Error: Command failed: pdffonts temp/README.md > temp/README.md
Syntax Error: Document stream is empty

onFulfilled true
ファイル書き出しOK=>manifest.json
ファイル書き出しOK=>README.md
ファイル書き出しOK=>Chrome拡張MV3について.pdf

今度は、成功しました。エラーも発生していますが、こちらはpdfファイルでないファイルに対してpdffontsを実行したため発生したエラーです。念の為pdfファイル以外が添付されていた場合には、処理対象外にするようにしたほうが良さそうです。
pdffontsの実行結果のファイルも確認します。

Chrome拡張MV3について.txtに出力されたpdffontsの実行結果
pdffontsの実行結果

今日のまとめ

対象レコードから取得した添付ファイルの情報をもとに、添付ファイルをダウンロードして、pdffontsの実行結果をファイルに保存するところまで確認できました。ここまでの実装で、非同期処理のPromiseについても理解が進んだ気がします。しかし、まだ理解が浅いので、引き続き学習を続けます。

この記事が気に入ったらサポートをしてみませんか?