開発情報・ナレッジ

投稿者: ShiningStar株式会社 2024年8月26日 (月)

GoogleColab上でSPIRALのDBのファイルをGoogleドライブにアップロードしてみた

GoogleColab を使ってSPIRALのDBにアップロードされているファイルをGoogleDriveにアップロードするプログラムを作成してみました。
GoogleColabとはGoogleの環境上でPythonコードを実行出来るサービスとなります。
GoogleColabを利用することで他のGoogleサービスとの連携が簡単にできるので、お試しください。


全体像

GoogleDriveをマウントし操作可能にした上で、
SPIRALのAPIを使用してファイルをダウンロードして一時ファイルに保存し、
そのファイルをGoogleドライブへコピーしてアップロードします。

DB設定

ファイルフィールドを持つDBであれば利用可能です。
そのDBのファイルフィールドのIDとフィールド識別名を控えてください。
本サンプルはファイルフィールドに複数ファイルを登録した場合でも稼働する形になっています。

サンプルプログラム

import requests
import os
import shutil
from google.colab import drive
import time

# Googleドライブをマウント
drive.mount('/content/drive')

# 設定値
API_URL = "https://api.spiral-platform.com/v1"
API_KEY = "" # SPRIALのAPIキー
APP_ROLE = "" #SPIRALの設定にてロールが指定されている場合は記入
DB_ID = ""
APP_ID = ""
delete_flg = 1  # ファイル削除フラグ(1: 削除する、0: 削除しない)
file_field_name = "file"  # ファイルフィールド名
file_field_id = "1"  # ファイルフィールドID
google_drive_folder_path = '/content/drive/My Drive/fromspiral/'  # アップロード先フォルダパス

# SPIRAL APIにリクエストを送信してデータを取得する関数
def api_curl_action(method, url, headers=None, data=None, return_json=True):
    headers = headers or {
        "Authorization": f"Bearer {API_KEY}",
        "X-Spiral-Api-Version": "1.1",
        "Content-Type": "application/json"
    }

    response = requests.request(method, API_URL + url, headers=headers, json=data)

    if return_json:
        try:
            return response.json()
        except requests.exceptions.JSONDecodeError:
            if method == "DELETE":
                return None
            else:
                print("JSONデコードエラー: レスポンスがJSON形式ではありません。")
                return None
    else:
        return response.content

# ファイル情報を取得
url = f"/apps/{APP_ID}/dbs/{DB_ID}/records"
result_record_list_select = api_curl_action("GET", url)

file_infos = []
if result_record_list_select and 'items' in result_record_list_select:
    for record in result_record_list_select['items']:
        if file_field_name in record:
            for file in record[file_field_name]:
                if 'fileKey' in file and 'fileName' in file:
                    download_url = f"/apps/{APP_ID}/dbs/{DB_ID}/{file_field_id}/{record['_id']}/files/{file['fileKey']}/download"
                    file_infos.append({
                        'fileName': file['fileName'],
                        'fileKey': file['fileKey'],
                        'url': download_url,
                        'recordId': record['_id']
                    })

# ファイルのダウンロードとGoogle Driveへのアップロード
for file_info in file_infos:
    # SPIRALからファイルをバイナリデータとしてダウンロード
    file_data = api_curl_action("GET", file_info['url'], headers=None, return_json=False)
    # print(file_data) //SPIRALからファイルをダウンロードできてない場合はこちらで確認

    if file_data:
        # ファイルをローカルに保存
        local_file_path = os.path.join('/tmp', file_info['fileName'])
        with open(local_file_path, 'wb') as file:
            file.write(file_data)

        # Google Driveにファイルをコピー(リトライ機能付き)
        for attempt in range(3):  # 最大3回リトライ
            try:
                drive_file_path = os.path.join(google_drive_folder_path, file_info['fileName'])
                shutil.copy2(local_file_path, drive_file_path)
                print(f"ファイル '{file_info['fileName']}' のGoogle Driveへのアップロードが成功しました。")

                # コピーが成功したらローカルファイルを削除
                os.remove(local_file_path)
                break  # 成功したのでループを抜ける
            except Exception as e:
                print(f"アップロード中にエラーが発生しました: {e}")
                time.sleep(5)  # 5秒待ってから再試行
        else:
            print(f"ファイル '{file_info['fileName']}' のGoogle Driveへのアップロードに失敗しました。")
        #アップロード完了後の処理を追加したい場合は下記へ追加してください。
        # レコード削除
        if delete_flg == 1:
            # ファイルを削除するためにSPIRALのレコードを更新
            fileKey = ""  # 空の値を指定
            recordId = file_info['recordId']
            files = []

            if fileKey:  # fileKeyが空でない場合のみリストに追加
              files.append(fileKey)

            update_data = {
            file_field_name: files
           }

            # PATCHリクエストを送信してレコードを更新
            update_url = f"/apps/{APP_ID}/dbs/{DB_ID}/records/{recordId}"
            api_response = api_curl_action("PATCH", update_url, data=update_data)
            # print(api_response) //SPIRALの更新がうまく行っていない場合はこちらを確認
            if api_response is not None:
                print(f"レコード '{recordId}' のファイル削除が成功しました。")
            else:
                print(f"レコード '{recordId}' のファイル削除に失敗しました。")

    else:
        print(f"ファイル '{file_info['fileName']}' のダウンロードに失敗しました。")
 
            

GoogleDriveのパスの確認方法

データをアップロードする時にアップロードしたいファイルのパスを確認する必要があります。

from google.colab import drive

# Google Driveをマウント
drive.mount('/content/drive') 
            

こちらのGoogleDriveをマウントする記述のみをコードブロックに貼り付けて実行する事で、
サイドバーのファイル欄からディレクトリを確認することができます。

設定方法

GoogleColabへアクセスして新規ノートブックを作成してください。
作成したら上記サンプルプログラムをそのまま貼り付けてください。
GoogleDriveのパスがご不明な方は上記のGoogleDriveのパスの確認方法に従ってパスを確認してください。
後に、

# 設定値
API_URL = "https://api.spiral-platform.com/v1"
API_KEY = ""
APP_ROLE = ""
DB_ID = ""
APP_ID = ""
delete_flg = 1  # ファイル削除フラグ(1: 削除する、0: 削除しない)
file_field_name = "file"  # ファイルフィールド名
file_field_id = "1"  # ファイルフィールドID
google_drive_folder_path = '/content/drive/My Drive/fromspiral/'  # アップロード先フォルダパス

こちらをお使いの環境に合わせて修正してください。
その他は変更せずに稼働いたします。

修正が終わったら、
左上にあります再生ボタンの様なボタンを押すとプログラムが実行され、
SPIRALのファイルがGoogleドライブへアップロードされます。
本サンプルプログラムではGoogleドライブへアップロードが完了したファイルを削除する機能も実装してあります。
削除したい場合はdelete_flgを1、削除したくない場合は0を指定して実行してください。

ファイル削除以外の処理をアップロード完了時に行いたい場合は、
「#アップロード完了後の処理を追加したい場合は下記へ追加してください。」
以下に条件式等含めて記載してください。

うまく動作しない場合

Googleドライブ側でアップロードができているか確認する際に、
1分ほどラグがある可能性がありますので確認する際は少し時間を置いて確認してください。
SPIRALやGoogleドライブのAPIを実行した結果をprintする様にコメントアウトで記載しています。
問題が起きている場合は各種printのコメントアウトを外しどの様なエラーが起きているか確認してください。

その他

GoogleColab上では他のGoogleサービスとの連携がかなり容易でAPI認証等必要ないので、
例えば他には容易にGmailのデータをSPIRALに格納することが出来ます。
GoogleサービスとSPIRALの連携には非常に良い環境なので、
GoogleサービスとSPIRALのデータ連携をする場合は是非GoogleColabの利用をご検討頂けると幸いです。
また、外部環境との連携ですのでデータの取扱には十分にご注意ください。

解決しない場合はこちら コンテンツに関しての
要望はこちら