全国オンライン対応受付 平日 9:00-18:00
お問い合わせ

開発記録 / Fuhne制作記 / Vol.16 Fuhne制作記 Vol.1

記事 03

管理画面に商品写真登録機能を追加した話——GASのDriveスコープとbase64アップロード

「商品写真も管理画面から登録できるようにしたい」というリクエストが来た。

2026-06-07 公開

「商品写真も管理画面から登録できるようにしたい」というリクエストが来た。

考えてみると当然の要求だ。新しいタルトを作った。写真を撮った。それを注文フォームに反映させるために、開発者にファイルを送って対応を依頼する。そのフローはオーナーにとって不便だし、開発者にとっても余分な仕事だ。

自分でできるようにする。そのための機能を管理画面に追加した。


ファイルをGASに渡す方法

ブラウザからGASにファイルを送る方法は1つしかない。base64エンコードだ。

ブラウザはファイルをbase64の文字列に変換する。GASがその文字列を受け取り、Blobに戻してGoogle Driveに保存する。

// ブラウザ側
function uploadProductImage(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function(e) {
      const base64 = e.target.result.split(',')[1];
      google.script.run
        .withSuccessHandler(resolve)
        .withFailureHandler(reject)
        .uploadImage(file.name, file.type, base64);
    };
    reader.readAsDataURL(file);
  });
}

e.target.resultdata:image/jpeg;base64,/9j/4AAQ...という形式だ。split(',')[1]で「/9j/4AAQ...」の部分だけを取り出してGASに渡す。


GASがDriveに保存できない——スコープの罠

ブラウザ側を実装してテストした。GASにbase64データは届いた。DriveApp.createFile()を呼んだ。権限エラーが返ってきた。

GASのWebアプリは、使用するAPIのスコープをappsscript.jsonに宣言しなければならない場合がある。DriveApp.createFile()だけではコードの解析で自動検出されないことがある。

appsscript.jsonにDriveスコープを明示的に追加した。

{
  "timeZone": "Asia/Tokyo",
  "oauthScopes": [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/gmail.send",
    "https://www.googleapis.com/auth/script.external_request"
  ]
}

GASのエディタではappsscript.jsonはデフォルトで非表示だ。「表示」→「appsscript.json マニフェストファイルを表示する」をONにすると編集できる。

再デプロイすると動いた。


GAS側の実装

function uploadImage(filename, mimeType, base64Data) {
  const blob = Utilities.newBlob(
    Utilities.base64Decode(base64Data),
    mimeType,
    filename
  );
  const folder = DriveApp.getFolderById(IMAGE_FOLDER_ID);
  const file = folder.createFile(blob);
  file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);

  return 'https://lh3.googleusercontent.com/d/' + file.getId();
}

Utilities.base64Decode()でbase64をbyte配列に戻し、Utilities.newBlob()でBlobを作る。フォルダに保存し、リンクを知っている全員が閲覧できる権限を設定する。


URLの形式にこだわった

Google DriveのファイルURLには種類がある。

drive.google.com/file/d/FILE_ID/viewはファイルの表示ページURL。ブラウザで開くとDriveの画面が出る。imgタグのsrcには使えない。

drive.google.com/uc?id=FILE_IDは直リンクのつもりだが、GoogleがHTMLリダイレクトを返すことがあり、imgタグで使うと表示されないことがある。

lh3.googleusercontent.com/d/FILE_IDはGoogleフォト系の配信URL。imgタグのsrcに直接使えて、ブラウザが追加リダイレクトを挟まずに画像を受け取れる。

焼き菓子店では3番目の形式を使った。注文フォームの商品写真がきちんと表示されるかどうかは、このURL形式の選択に依存していた。


非表示商品の扱い

商品を「販売停止」にする機能も実装した。フロントエンドには販売中フラグがONの商品だけをAPIが返す。

非表示の商品データをフロントエンドに送らない設計にした。ブラウザの開発者ツールを開いて通信を確認しても、販売停止商品の情報は見えない。

「実は別の商品があるらしい」という情報は、お客さんには必要ない。


*シンプルシステム株式会社 代表 伊藤勝彦*