LoginSignup
3
1

Googleドライブの画像をApps Scriptで作ったウェブアプリで使うには

Posted at

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つのステップが必要です。

  1. Googleドライブ上で画像のアクセス権限を変更する
  2. 画像のファイルIDを調べる
  3. ファイル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を作ってウェブアプリで表示することができます。

  1. バックエンドにfetchDataUrl(fileId)を作る
  2. フロントエンドからfetchDataUrl(fileId)を呼び出す(同期型と非同期型がある)

ここではデモのため、ウェブアプリのURLにQueryパラメーターとしてtype=syncがあれば同期型、type=asyncがあれば非同期型で動作させることにします。

Code.gs
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を作ります。

Code.gs
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を作成して画面に埋め込んでから、返信します。

Sync.html
<!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を呼び出します。

Async.html
<!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で画像をホスティングするなど、別の方法を取ったほうが良さそうです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1