markdown

はじめに (対象読者・この記事でわかること)

このブログは、Google Apps Script(GAS)初心者から中級者を対象に、Web フォームや外部サービスから取得した Base64 文字列を Google Drive に画像ファイルとして保存する具体的な方法を解説します。読者は、GAS のスクリプトエディタ上で Base64 データをデコードし、Blob オブジェクトへ変換、さらに Drive API を使って任意のフォルダに保存できるようになります。実務でレポート自動生成やメール添付画像の保存を自動化したい方に特に有用です。執筆のきっかけは、社内ツールで画像を直接保存できず手作業が発生していた問題をスクリプトで解決した経験です。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。
- Google Apps Script の基本的な構文と実行方法
- HTML の <img> タグやデータ URL(data:image/png;base64,…)の概念
- Google Drive のフォルダ構造と権限設定の基礎

Base64 画像を Drive に保存する概要

Web アプリや外部 API から取得する画像は、しばしば「data:image/png;base64,....」という形式で文字列化されます。GAS ではこの文字列を直接ファイルに書き出すことはできませんが、Utilities.base64Decode() でバイナリに変換し、Utilities.newBlob() で Blob オブジェクトにラップすれば、Drive に保存可能です。ここで重要になるのは、Base64 ヘッダー(data:image/png;base64, など)を除去し、正しい MIME タイプを設定することです。また、保存先フォルダの ID を取得しておくことで、整理された形でファイルを管理できます。本セクションでは、必要な概念と注意点をまとめます。

  • Base64 デコード: Utilities.base64Decode(base64Str) がバイト配列を返す。
  • Blob 生成: Utilities.newBlob(bytes, mimeType, fileName) で Blob を作成。
  • Drive への保存: DriveApp.getFolderById(folderId).createFile(blob) でフォルダ内にファイル作成。
  • エラーハンドリング: デコード失敗や権限不足は try...catch で捕捉し、ログに詳細を出力する。

実装手順:Base64 画像を Drive に保存するスクリプト

以下では、実際に動作するサンプルコードとともに、ステップごとに解説します。

ステップ 1:スクリプトの準備とテストデータの作成

  1. Google ドライブで保存先フォルダを作成し、フォルダ ID を取得(URL の folders/ 以下の文字列)。
  2. GAS のプロジェクトを作成し、コードエディタに以下のサンプル関数を貼り付ける。
Javascript
/** * Base64 画像文字列を Drive の指定フォルダに保存する * @param {string} base64Str - data URL 形式の Base64 文字列 * @param {string} folderId - 保存先フォルダの ID * @param {string} fileName - 保存するファイル名(拡張子含む) * @return {File} 保存された Drive ファイルオブジェクト */ function saveBase64ImageToDrive(base64Str, folderId, fileName) { // ヘッダー部分 (data:image/png;base64,) を除去 var matches = base64Str.match(/^data:(image\/\w+);base64,(.+)$/); if (!matches) { throw new Error('Invalid Base64 image data'); } var mimeType = matches[1]; var data = matches[2]; // Base64 をデコードしてバイト配列取得 var decodedBytes = Utilities.base64Decode(data); // Blob に変換 var blob = Utilities.newBlob(decodedBytes, mimeType, fileName); // フォルダ取得 var folder = DriveApp.getFolderById(folderId); // ファイル作成 var file = folder.createFile(blob); return file; }

この関数は、Base64 文字列と保存先フォルダ ID、ファイル名を受け取り、Drive に PNG、JPEG など任意の画像形式で保存します。matches[1] が MIME タイプ、matches[2] が実際の Base64 データです。

ステップ 2:実際に呼び出すサンプルコード

Javascript
function testSaveImage() { // 例として、1x1 ピクセルの赤い PNG データ URL を使用 var base64Image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO0jKXcAAAAASUVORK5CYII='; var folderId = 'YOUR_FOLDER_ID_HERE'; // ← ここに取得したフォルダ ID を設定 var fileName = 'sample_red.png'; try { var file = saveBase64ImageToDrive(base64Image, folderId, fileName); Logger.log('File saved: ' + file.getUrl()); } catch (e) { Logger.log('Error: ' + e.message); } }

testSaveImage を実行すると、指定フォルダに sample_red.png が作成され、ログにファイル URL が出力されます。これで基本的な保存は完了です。

ステップ 3:実務での応用例(Web フォームからの受信)

Google フォームや HTML フロントエンドから画像を Base64 文字列で送信するケースが多いです。以下は、Web アプリとしてデプロイし、POST リクエストで受け取った画像を保存する例です。

Javascript
/** * doPost エンドポイント:HTML フォームから Base64 画像を受信し保存 */ function doPost(e) { var params = JSON.parse(e.postData.contents); var base64Str = params.image; // { "image": "data:image/jpeg;base64,...." } var folderId = params.folderId; // 任意でクライアント側からフォルダ ID を受け取る var fileName = params.fileName || 'uploaded_image.jpg'; try { var file = saveBase64ImageToDrive(base64Str, folderId, fileName); return ContentService .createTextOutput(JSON.stringify({status: 'success', url: file.getUrl()})) .setMimeType(ContentService.MimeType.JSON); } catch (err) { return ContentService .createTextOutput(JSON.stringify({status: 'error', message: err.message})) .setMimeType(ContentService.MimeType.JSON); } }

このスクリプトを「ウェブアプリとして導入」し、exec URL に対して {image: "...", folderId: "...", fileName: "..."} の JSON を POST すれば、サーバ側で即座に画像が保存されます。フロントエンド側は fetch API で簡単に連携できます。

ハマった点やエラー解決

発生した問題 原因 解決策
「Invalid Base64 image data」エラー 受信した文字列に data:image/...;base64, ヘッダーが欠落または余計な改行が混入 正規表現でヘッダーを抽出し、余分な空白や改行 (\n, \r) を replace で除去
保存したファイルが 0 バイト Utilities.base64Decode() に渡す文字列がエンコード済みのまま二重エンコードされていた decodeURIComponent(escape(atob(...))) のような二重デコード処理は行わず、純粋な Base64 部分だけをデコード
権限エラー (Exception: You do not have permission to call DriveApp) スクリプトが「外部からのアクセス」用にデプロイされていなかった 「ウェブアプリとして導入」時に「全員(ログインが必要)」ではなく「全員(匿名ユーザー含む)」に変更し、必要なスコープ https://www.googleapis.com/auth/drive を付与
ファイル名が重複して上書きされる createFile は同名のファイルを別ファイルとして作成するが、フォルダ内が混乱 Utilities.formatDate(new Date(), "JST", "yyyyMMdd_HHmmss") を付与して一意な名前にする

解決策のベストプラクティス

  1. ヘッダー除去は必ず正規表現で/^data:(image\/\w+);base64,(.+)$/ が最も安全。
  2. エラーハンドリングは必須try...catch で例外を捕捉し、Logger.log か HTTP レスポンスで詳細を返す。
  3. ファイル名の一意性:タイムスタンプや UUID (Utilities.getUuid()) を組み合わせる。
  4. スコープ管理appsscript.json"oauthScopes": ["https://www.googleapis.com/auth/drive"] を明示的に記載すると、権限承認がスムーズになる。

まとめ

本記事では、Google Apps Script を用いて Base64 文字列から画像ファイルを Google Drive に保存する手順を、概念から実装例、エラーハンドリングまで網羅的に解説しました。
- Base64 デコードと Blob 生成 が鍵。
- 正規表現でヘッダー除去、MIME タイプ設定を忘れずに。
- Drive API と適切な権限 を組み合わせれば、Web フォームや外部サービスからの画像保存が自動化できる。

この記事を通じて、開発者は「画像データの受取→保存」フローをコードだけで完結させ、手作業の削減とプロセスの標準化が実現できます。次回は、保存した画像をサムネイル加工し別フォルダに分類する方法や、Google Slides への自動貼り付けテクニックを紹介する予定です。

参考資料