🐋

【Python】Djangoで受け取ったUploadedFileをGoogleCloudStorage(GCS)にアップロードしたり削除する

2024/11/17に公開

概要

Djangoでアップロードされたファイルを受け取る際はアップロードファイルとアップロードハンドラの記事にある通り、UploadedFileのオブジェクトとして受け取ります。今回は、このオブジェクトをGoogleCloudStorage(GCS)にアップロードしたり、削除したりする実装をメモ書きします。
なお、GCSのアクセスに使うライブラリはgoogle-cloud-storageになります。

前提

  • 使用したDjangoのバージョンは5.1.2です。
  • 使用したgoogle-cloud-storageのバージョンは2.18.2です。

実装

まずはバケットへの接続とアップロード・削除のメソッドを用意します。

import io
from google.cloud import storage
from google.cloud.storage.bucket import Bucket
from google.oauth2 import service_account

from sample.settings import ENV

# 環境変数からバケットを取得
def get_gcs_bucket() -> Bucket:
    credential = service_account.Credentials.from_service_account_file(
        ENV.get_value("GCS_KEY_PATH")
    )
    storage_client = storage.Client(
        project=ENV.get_value("GOOGLE_PROJECT_ID"), credentials=credential
    )
    bucket = storage_client.bucket(ENV.get_value("GCS_BUCKET"))
    return bucket

# BytesIOにしたファイルをアップロード
def upload_file_gcs(file_path: str, file_obj: io.BytesIO) -> str:
    # バケットを取得
    bucket = get_gcs_bucket()
    # アップロード
    blob = bucket.blob(file_path)
    blob.upload_from_file(file_obj)
    # 参照用のURLを返す
    return blob.public_url

# ファイルパスを指定してファイルを削除
def delete_file_gcs(file_path: str):
    # バケットを取得
    bucket = get_gcs_bucket()
    # 削除
    blob = bucket.blob(file_path)
    blob.delete()

アップロードと削除の呼び出し元です。

import os
import uuid
from django.core.files.uploadedfile import UploadedFile


UPLOAD_FOLDER: str = "sample_folder"

def upload_icon_image_file(file_uploaded: UploadedFile) -> str:
    # 拡張子を取得
    ext = os.path.splitext(file_uploaded.name)[1]
    # 新しくファイル名を割り振る
    new_file_name = str(uuid.uuid4())
    file_path = f"{UPLOAD_FOLDER}/{new_file_name}{ext}"
    # 上記のアップロードメソッドを呼び出し
    return upload_file_gcs(file_path, file_uploaded.file)

# 発行されたURLからファイルパスを取得して削除
def delete_icon_image_file(image_url: str):
    file_name = image_url[image_url.rfind("/") + 1 :]
    file_path = f"{UPLOAD_FOLDER}/{file_name}"
    # 上記の削除メソッドを呼び出し
    delete_file_gcs(file_path)

参考

Discussion