「商品写真も管理画面から登録できるようにしたい」というリクエストが来た。
考えてみると当然の要求だ。新しいタルトを作った。写真を撮った。それを注文フォームに反映させるために、開発者にファイルを送って対応を依頼する。そのフローはオーナーにとって不便だし、開発者にとっても余分な仕事だ。
自分でできるようにする。そのための機能を管理画面に追加した。
ファイルを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.resultはdata: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が返す。
非表示の商品データをフロントエンドに送らない設計にした。ブラウザの開発者ツールを開いて通信を確認しても、販売停止商品の情報は見えない。
「実は別の商品があるらしい」という情報は、お客さんには必要ない。
*シンプルシステム株式会社 代表 伊藤勝彦*