Google Cloud FunctionsでパスワードPDFを作る【GAS】
前回の記事で、Google Apps ScriptからGoogle Cloud Storageへのファイルのアップロードを実現しました。しかし、目的はパスワード付PDFを作ること。そのためにはまだいくつものハードルがあります。
今考えているのは、スプレッドシートのID、Access Token、設定パスワードをなげて、Google Cloud Functions上 の関数でPDFを生成。そのPDFを続けて、パスワード付PDFに変換し、Google Cloud Storageに格納。それをGAS側へ返却するというプランです。今回はその中間である、「Cloud StorageにあるPDFをパスワード付PDFにして、Cloud Storageに格納する」という処理を、Cloud Functionsで実装してみました。
目次
事前準備
Cloud Storage
今回の処理で必要な手順は以下の通り。
- Cloud Storage(バケットの名前は、drive2gcsにしておきました)に、フォルダ(publicという名前にしました)を作成する
- 1.のフォルダの中に、テスト用のPDFを1個だけアップロードします(test.pdfという名前ににしました)。
Cloud Storage側はこれだけです。
Cloud Functions
Cloud Functions側の準備もシンプルです。事前にサービスアカウントの作成が必要ですので、作成をしておきましょう。前回の記事で作成について触れています。もちろん請求先アカウントの設定も必要です。
- 関数を作成する
- 割当メモリは512MB、トリガーはHTTPとしました。ランタイムはNode.js V8を選んでいます。
- リージョンは、デフォルトのus-central1にしてあります。
- 関数名は、encryptPDFという名前にしました。しかし、実際に呼び出す関数はコードの中にある「passpdf」になりますので、注意。
- Cloud Functions上では、npmでインストールではなく、package.jsonに記述すると裏でモジュールを用意してくれます。ですので、以下のような記述を追加しました。追加モジュールは2個です。
- hummus-recipeは、PDFをパスワード付にするだけでなく、様々な加工のできるスグレモノです。
- google-cloud/storageは、Google作成のNode.jsからCloud Storageへのアクセスを容易にするモジュールです。
- 実行する関数名は、passpdfとして設定しました。
1 2 3 4 5 6 7 8 |
{ "name": "sample-http", "version": "0.0.1", "dependencies": { "hummus-recipe": "^1.8.9", "@google-cloud/storage": "^2.5.0" } } |
図:package.jsonには以上のような記述を追加
Cloud Functionsの仕様と料金
Cloud Functionsでは、一時的に利用するディレクトリとして、/tmpが用意されています。また、料金はCloud Storageに加えて、こちらの料金表が適用されます。但し月間呼び出し回数が200万回以下の場合には、無料で利用できます。お得ですね。コンピューティング時間による金額は請求されますが、今回の設定ですと、100ms = $0.000000925となっています。
/tmpのサイズは自分で設定したメモリサイズの中から利用されます。あまり大量に生成すると、メモリが枯渇しますので注意が必要なのと、少ないリソースで設定してしまうと、関数の実行も遅くなってしまうので、注意。
実行中のデバッグやログは、Stack Driver Loggingが利用されます。
コードと実行
ソースコード
メイン画面の編集をクリックするとソースコードなどを編集可能です。インラインエディタ以外にも、ファイルをアップロードで環境を作ることも可能です。
今回これでCloud Functions側の実装が完了したので、GAS側から受け付ける為の改造を追加して完了になりますが、まだハードルが少しある(このままでは、最低3回はGAS側でUrlfetchAppを実行しなければならないので、これを1回で済ますようにするには、まだロジックが必要)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
//標準モジュールの読み込み var fs = require('fs'); //追加モジュールの読み込み const HummusRecipe = require('hummus-recipe'); const {Storage} = require('@google-cloud/storage'); //バケットとtmpフォルダの指定 const gcs = new Storage(); const bucket = gcs.bucket('drive2gcs'); const tempFilePath = "/tmp/" //呼び出す関数の設定 exports.passpdf = (req, res) => { //GCSのファイル読み込み var file = bucket.file("/public/test.pdf"); new Promise(function(resolve, reject) { //ファイルダウンロード file.download({ destination: tempFilePath + "test2.pdf" }).then(()=>{ resolve("OK"); }); }).then((result) => { //ダウンロード完了 console.log(result); //パスワード化を実施する passwordpdf(function (ret){ //パスワード化完了 console.log(ret); //GCSへアップロードする var options = { destination: "/public/output.pdf" }; bucket.upload(tempFilePath + "output.pdf", options, function(err, file) { console.log("File Uploaded"); }).then(()=>{ return; }); }); }).then((result) => { //ファイルサイズを取得する var stat = fs.statSync(tempFilePath + "output.pdf"); console.log(stat.size + "バイト"); let message = req.query.message || req.body.message || stat.size + "バイト"; res.status(200).send(message); }); } //PDFにパスワード化を実施する function passwordpdf(callback){ const pdfDoc = new HummusRecipe(tempFilePath + "test2.pdf", tempFilePath + "output.pdf"); var ret = pdfDoc.encrypt({ userPassword: '123', ownerPassword: '123', userProtectionFlag: 4 }).endPDF(function(ret){ //5秒間スリープを入れる sleep(5000, function() { callback("Encryption End"); }); }); } //sleep関数 function sleep(waitSec, callback) { setTimeout(callback, waitSec); } |
- 冒頭でバケットやtmpなどの指定を行っておきます。
- 実際にパスワードPDFを作成するのはpasswordpdf関数になります。
- passpdf関数がメインの関数となり、これを呼び出します。
- GCSからファイルをtmpフォルダにダウンロード、パスワード付与、アップロード、ファイルサイズ取得までが一連の流れです。
- ダウンロードした時のファイル名は、test2.pdfという名称にしています。
- Node.jsですのでそのまま記述してしまうと、非同期に進んでしまいますので、Promiseで同期的に実行させる必要があります。
- また、PDF生成時に5秒間のsleepを入れています。時々生成前にPDFのアップロードまで進んでしまう事があったので、そのための処置です。
- pdfDoc.encryptメソッドにてパスワードを付与しています。ここで設定したパスが開くときのパスワードになります。
- Bufferではなくローカル(tmp以下のフォルダ内)のファイルへアクセスが必要なので、HummusRecipeの引数では、ダウンロードしたファイルパスと出力時のファイルパスを入れてます。
- output.pdfとしてパスワード付PDFがtmpに作成されます。
- bucket.uploadにて作成したPDFファイルをGCSにアップロードさせています。
図:メインの編集画面
実行してみる
コードを記述したら、
- メイン画面の一番下にある「デプロイ」をクリックする
- モジュールの準備やコードの精査などが開始されます。問題がある場合にはエラー表示がなされ、ログはStackDriver Loggingに記録されています。
- 完全に完了すると、待機する状態になります。
- 完全に完了したら、トリガーをクリックし、URLが表示されるのでクリックすると作動します。
- 今回のプログラムでは、最後にPDFのファイルサイズを返しています(毎回ちょっとずつ、ファイルサイズが違うけれど、きちんと開けています)。
- きちんと実行が完了すると、GCS側のバケット内にoutput.pdfが生成されます(少し時間差があります)。
図:実行したらきちんとファイルがアップされてました。
図:きちんとパスワード付きになってるのを確認
関連リンク
- Google Cloud Functions bucket.upload()
- Cloud Functionsで動的に画像変換
- Google Cloud Functions (GCF)入門! GCFを使ってGoogle Cloud Storage (GCS)のファイルを自動で圧縮する
- Node.js - Upload File to Google Cloud Storage
- NodejsでGoogle Cloud Storageへファイルをアップロードしてみる
- 【Node.js入門】誰でも作れるsleep関数を自作する方法まとめ!
- Puppeteer + GCP Functionsでサーバレスなスクレイピング
- 【Firebase】Cloud Functionsで学ぶPromiseとasync/await
- 5分でCloud FunctionsからCloud Storageのファイルを参照して中身を返却するAPIを作る
- Cloud Storage for Firebaseにアップロードした画像のサムネイルをCloud Functionsを利用して作成する(Node.js)
- Cloud Functions ローカル エミュレータ
- GCPのGoogle Cloud Functionsで複数画像を合成して1枚のOGPを作成する
- galkahana/HummusJS - 今回利用するものとはまた別のPDF化のモジュール
- [Google Cloud Functions]でQRコード作成APIを構築!