Google Apps Scriptを使うと無料でウェブアプリを開発できます。
この記事ではApps Scriptで作ったウェブアプリ上で、Googleドライブに保存した画像を利用する方法をいくつかご紹介します。なお非公式な方法もご紹介しますが、今後使えなくなる可能性があることにご注意ください。
ずっと使えるか? | Googleドライブの画像をウェブアプリで使う | 補足 |
---|---|---|
ずっと使える | iframe | |
ずっと使える | Google Cloud Storageで画像をホスティング | Google Cloudが必要 |
ずっと使える | Cloud FunctionsでDriveから画像を取得 | Google Cloudが必要 |
ずっと使える | プロキシーサービス https://lienuc.com を使う | 有料 |
使えなくなった | https://drive.google.com/uc?export=view&id={ファイルID} |
2024年1月まで |
使えなくなるかも | https://lh3.google.com/u/0/d/{ファイルid} |
|
使えなくなるかも | https://drive.google.com/thumbnail?id={ファイルid}&sz=w1000 |
|
ずっと使える | Apps ScriptでデータURLを作る | 動作が遅い |
Googleドライブ上の画像をApps Scriptのウェブアプリで使う公式な方法
Googleが公式に認めているのは、<iframe>
タグを使って画像を埋め込むやり方です。詳しくは
にやり方が書いてあります。Googleドライブで画像ファイルを指定して、ケバブメニューからEmbed item...
を選ぶとHTMLのソースコードをコピーできます。
例えば、https://drive.google.com/file/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu/view という画像の場合、<iframe>
を使うコードは次のようになります。
<iframe
src="https://drive.google.com/file/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu/preview"
width="640"
height="480"
allow="autoplay"
></iframe>
しかし<iframe>
は使い勝手がよくありません。Google Issue Trackerでのやり取りで、それ以外の方法も紹介されています。
- Google Cloud Storageで画像データをホスティングする
- Cloud FunctionsでGoogleドライブから画像データを取得する
- 他社のプロキシーサービス https://lienuc.com を利用する
2024年1月時点で使えなくなった非公式な方法
以前は、<img>
タグのsrc
属性にhttps://drive.google.com/uc?export=view&id={ファイルID}
を指定する方法が使えていました。しかし、Googleがサードパーティ・クッキーの廃止を進めている影響で、2024年1月以降はこの方法は使えなくなっています。ウェブアプリの画面に画像は表示されず、デベロッパーツールでネットワークタブを確認すると403 Forbidden
エラーが表示されます。
本件に関するGoogleからのアナウンスです。
Googleドライブ上の画像をApps Scriptのウェブアプリで使う非公式な方法
いつ使えなくなるか分かりませんが、2024年1月時点で使える方法があるのでご紹介します。次の3つのステップが必要です。
- Googleドライブ上で画像のアクセス権限を変更する
- 画像のファイルIDを調べる
- ファイルIDから画像のURLを作成する
1. Googleドライブ上で画像のアクセス権限を変更する
公式ヘルプを参考に設定します。ウェブアプリで画像を使う場合、ファイルを一般公開で共有する
ことが多いです。
2. 画像のファイルIDを調べる
Googleドライブ上で画像を選択すると、そのURLはhttps://drive.google.com/file/d/{ファイルID}/view
の形式になっています。
例えば、https://drive.google.com/file/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu/view という画像の場合、ファイルIDは1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu
です。
3. ファイルIDから画像のURLを作成する(その1)
<img>
タグのsrc
属性にhttps://lh3.google.com/u/0/d/{ファイルid}
を指定することで、画像を表示できます。
https://drive.google.com/file/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu/view という画像の場合、
<img src="https://lh3.google.com/u/0/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu">
となります。
3. ファイルIDから画像のURLを作成する(その2)
<img>
タグのsrc
属性にhttps://drive.google.com/thumbnail?id={ファイルid}&sz=w1000
を指定する方法も利用できます。なお、画像URLのsz
で指定した横幅が、<img>
タグのwidth
属性より優先されるのでご注意ください。
https://drive.google.com/file/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu/view という画像の場合、
<img src="https://drive.google.com/thumbnail?id=1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu&sz=w1000">
となります。
Apps ScriptでデータURLを作って表示する方法
動作速度は遅くなりますがApps ScriptでデータURLを作ってウェブアプリで表示することができます。
- バックエンドに
fetchDataUrl(fileId)
を作る - フロントエンドから
fetchDataUrl(fileId)
を呼び出す(同期型と非同期型がある)
ここではデモのため、ウェブアプリのURLにQueryパラメーターとしてtype=sync
があれば同期型、type=async
があれば非同期型で動作させることにします。
function doGet(e) {
const type = e.parameter.type;
if (type === 'sync') {
return HtmlService.createTemplateFromFile('Sync').evaluate();
}
if (type === 'async') {
return HtmlService.createHtmlOutputFromFile('Async');
}
return HtmlService.createHtmlOutput('Queryパラメーター type が不正です。sync もしくは async にする必要があります:' + type);
}
同期型と非同期型の違いは、ウェブアプリが画像を表示するまでの処理の流れにあります。ウェブアプリの用途に応じてどちらが良いか選択してください。
-
**同期型(Synchronous)**では、ウェブアプリがブラウザに表示される前に、サーバー側で画像のデータURLをすべて取得してHTMLに組み込みます。この方法は、すべての画像データが準備できるまでユーザーは何も見ることができません
-
**非同期型(Asynchronous)**では、ウェブアプリのHTMLを先にブラウザに表示します。その後、JavaScriptを使ってバックグラウンドで画像のデータURLを取得し、画像がダウンロードされ次第、それぞれの画像を表示します。この方法は、画像以外のコンテンツを先に見せるので、ユーザー体験が改善することがあります
1. バックエンドにfetchDataUrl(fileId)
を作る
GoogleドライブのfileId
を指定して、データURLを作ります。
function fetchDataUrl(fileId) {
const blob = DriveApp.getFileById(fileId).getAs("image/webp");
const contentType = blob.getContentType();
const base64Data = Utilities.base64Encode(blob.getBytes());
return `data:${contentType};base64,${base64Data}`;
}
2. フロントエンドからfetchDataUrl(fileId)
を呼び出す(同期型)
ウェブアプリにアクセスがあると、すべての画像のデータURLを作成して画面に埋め込んでから、返信します。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Data URL(Synchronous)</h1>
<img src="<?!= fetchDataUrl('1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu') ?>" width="480">
</body>
</html>
2. フロントエンドからfetchDataUrl(fileId)
を呼び出す(非同期型)
ウェブアプリにアクセスがあると、まずフロントエンドのHTMLを返信します。そしてgoogle.script.run
を使ってバックグラウンドでfetchDataUrl
を呼び出します。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Data URL (Asynchronous)</h1>
<img data-file-id="1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu" width="480">
<script>
window.onload = function() {
const images = document.querySelectorAll('img[data-file-id]');
for (let image of images) {
google.script.run.withSuccessHandler(dataUrl => {
image.src = dataUrl;
})
.withFailureHandler(err => console.error(`Could not call getDataUrl: ${err}`))
.fetchDataUrl(image.getAttribute('data-file-id'));
}
}
</script>
</body>
</html>
キャッシュを使った高速化が困難
https://drive.google.com/file/d/1dr139i1BCQpCFYOMTM054vuy6ih-8Dqu/view という画像の場合、生成されるデータURLの文字数は614,699
でデータ量は約615KBです。
CacheServiceで保存できるデータ量は100KBまで、PropertyServiceで保存できるのは9KBまで(一日当りの呼び出し回数にも上限あり)なので、生成したデータURLを保存するには容量が足りません。
また、スプレッドシートのセルの最大文字数は50,000文字までなので、セルをキャッシュ代わりに使うこともできません。
ということで、高速化のためにはGoogle Cloud Storageで画像をホスティングするなど、別の方法を取ったほうが良さそうです。