3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GCSからオブジェクトをダウンロードする署名付きURLの発行

Last updated at Posted at 2022-06-30

概要

  • GCSからデータダウンロードしたいですが、GAEを利用しているとタイムアウト値がstandardで60秒、flexibleで60分なので、容量がでかい場合、直接GCSからデータダウンロードしたくなると思います
  • 署名付きでやると公開されてしまうので嫌ですが、発行して直後に有効期限が切れて且つダウンロードは進むの要件でおkならそれでいいなってので試した内容になります
  • 今回はGCSへ保存しているデータは動画になります。利用する際は保存しているデータ形式あわせて修正すると良いです

ソースコード

from google.cloud import storage
from google.api_core.exceptions import NotFound
import os
from datetime import timedelta


def get_bucket():
    project_id = ""  # 設定してください
    client = storage.Client(project_id)
    bucket_name = ""  # 設定してください
    return client.get_bucket(bucket_name)


def get_suffix(content_type):
    # TODO: アップロードされる拡張子が増えたらここに追加.
    content_types = {
        'video/webm': '.webm'
    }
    suffix = content_types.get(content_type)
    if suffix is None:
        raise Exception('存在しない拡張子エラー: {}'.format(content_type))

    return suffix


def generate_signed_url(blob, blob_name, suffix):
    """署名付きダウンロードURLを発行する"""
    # response_typeでheaderをいじることができる(今回はダウンロードURLを発行する)
    response_type = \
        f"content-disposition=attachment; filename={blob_name}.{suffix}"
    return blob.generate_signed_url(
        version="v4",
        expiration=timedelta(seconds=30),
        method="GET",
        response_type=response_type
    )


def generate_download_url(filename):
    try:
        bucket = get_bucket()
        # blobを取得したらダウンロードせずとも拡張子がわかる.
        blob = bucket.get_blob(filename)
        suffix = get_suffix(blob.content_type)
        url = generate_signed_url(
            blob,
            filename,
            suffix
        )
        return url
    except NotFound as e:
        # 存在しないファイルをGCSからdownloadしようとした場合
        print(e)
    except Exception as e:
        print(e)

    return None


if __name__ == '__main__':
    url = generate_download_url('hogehoge')
    print(url)

簡易説明

環境

  • Python 3.10.x

準備

requirements.txt に下記追記して、インストールしましょう。

google-cloud-storage==2.4.0
$ pip install -r requirements.txt

あと環境変数にサービスアカウントのパスを指定してあげてください(発行方法や設定については省略)

GOOGLE_APPLICATION_CREDENTIALS_FILENAME=/project_root/credentials/hogehoge.json

Response headerの修正

動画の場合、署名付きURLを発行するだけだと、ブラウザでストリームで再生するようになりますが、ファイルとしてダウンロードしたいので、ヘッダーをつけています。 response_type にヘッダーをつけることができました。神!

有効期限が短いですが、発行後、すぐに踏んでダウンロードが開始することができるなら問題なしです。有効期限はアクセスの期限なので、ダウンロード中には適応されません。

今回は取得したURLをフロント側で <a></a> に設定して動的にclickさせるで対応しました。

response_type = f"content-disposition=attachment; filename={blob_name}.{suffix}"
return blob.generate_signed_url(
    version="v4",
    expiration=timedelta(seconds=30),  # 署名の有効期限
    method="GET",
    response_type=response_type
)

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?