開発情報・ナレッジ

投稿者: ShiningStar株式会社 2024年6月18日 (火)

SPIRAL上でGoogleDriveのファイルをダウンロードし、DBへ格納する方法

SPIRALのPHP(アクション>PHP実行)でGoogleDriveのファイルをダウンロードし、
SPIRALのDBへファイルを格納するサンプルプログラムをご紹介いたします。


全体像

GoogleDriveのAPIを用いてGoogleDrive内のファイルをダウンロードし、
そのファイルをSPIRALのAPIを用いてDBへアップロードします。

GoogleDriveのファイルをダウンロードするにはGoogleAPIのアクセストークンが必要なので取得します。
また、ダウンロードしたいファイルを指定するのにファイルIDも必要な為
GoogleDriveのAPIを用いてファイルIDを取得します。
ダウンロードが出来たらSPIRALのAPIに対して共通モジュールを使用しファイルをアップロードします。

DB設定

任意のDBを作成し、フィールドタイプでファイルを選択したフィールドを用意してください。
この際ファイルフィールドのIDとフィールド識別名を控えておいてください。

設定方法

Google側の設定(OAuth認証の作成)
Google側に任意のプロジェクトを作成していください。
その後Google側設定画面へアクセスしてください。
認証情報より「+認証情報を作成」をクリックして「OAuthクライアントID」をクリックしてください。
アプリケーションの種類は「ウェブアプリケーション」
承認済みのリダイレクトURIには「http://localhost/oauth2callback.php」と入力してください。
そのまま作成まで進み、モーダルに「クライアントID」と「クライアントシークレット」が表示されますので、必ず控えてください。

次に「OAuth同意画面」をクリックしてください。
「OAuth consent screen」では任意の情報を入力してください。
「スコープ」では何も入力しなくて大丈夫です。
「Test users」ではテストユーザにご自身のログインされているGoogleアカウント(Gmail)を入力してください。

ファイルのダウンロードをするにはアクセストークンが必要です。
しかし、アクセストークンには有効期限等があるので継続的にファイルのダウンロードが出来るように、
リフレッシュトークンを生成して、リフレッシュトークンからアクセストークンを都度生成する形にします。
設定値ファイルをPHPモジュールに作成

<?php
$client_id = 'クライアントIDを入力';
$client_secret = 'クライアントシークレットを入力';
$redirect_uri = 'http://localhost/oauth2callback.php'; 
            

モジュール名をconfig.phpとしてSPIRAL管理画面>アプリ設定>サイドバー>PHPモジュールより作成して上記を貼り付けてください。
ステップ1 リフレッシュトークンの取得

<?php
require_once "config.php";

$auth_code = ''; // 認証コードをここに入力

if (empty($auth_code)) {
    // 認証コードが入力されていない場合、認証URLを生成
    $auth_url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query([
        'client_id' => $client_id,
        'redirect_uri' => $redirect_uri,
        'response_type' => 'code',
        'scope' => 'https://www.googleapis.com/auth/drive.readonly',
        'access_type' => 'offline',
    ]);

    echo '認証URLをブラウザで開いて、認証コードを取得してください:';
    echo PHP_EOL . PHP_EOL;
    echo $auth_url . PHP_EOL;
} else {
    // 認証コードが入力されている場合、アクセストークンとリフレッシュトークンを取得
    $token_url = 'https://oauth2.googleapis.com/token';
    $post_fields = [
        'code' => $auth_code,
        'client_id' => $client_id,
        'client_secret' => $client_secret,
        'redirect_uri' => $redirect_uri,
        'grant_type' => 'authorization_code',
    ];

    $ch = curl_init($token_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));

    $response = curl_exec($ch);

    if ($response === false) {
        echo 'Error: ' . curl_error($ch);
        curl_close($ch);
        exit();
    }

    curl_close($ch);

    $token_data = json_decode($response, true);
    var_dump($token_data);
}
?>
 
            

上記プログラムをSPIRAL内アクション>PHP実行に設置して実行してください。
そうすると認証URLが出力されますので、そのURLをブラウザに貼り付けて遷移してください。
遷移するとエラーが表示されると思いますが、大丈夫です。
リダイレクトされた後URLに
http://localhost/oauth2callback.php?code=XXX&scope=YYYY
といった形でcodeのパラメータが付与されていますので、
このcodeパラメータ「XXX」を$auth_codeに代入して再度実行してください。
実行結果より「refresh_token」の値を控えてください。
作成したPHPモジュールを編集

<?php
$client_id = 'クライアントIDを入力';
$client_secret = 'クライアントシークレットを入力';
$redirect_uri = 'http://localhost/oauth2callback.php';

$refresh_token = "ステップ2で取得したリフレッシュトークンを入力"; 
            

$refresh_tokenの行を追記してください。
先ほど控えた値を$refresh_tokenの値に入力してください。
ステップ2 ファイルIDの取得

<?php
require_once "config.php";
$folder_id = ""; //フォルダIDを指定

$token_url = 'https://oauth2.googleapis.com/token';
$post_fields = [
    'refresh_token' => $refresh_token,
    'client_id' => $client_id,
    'client_secret' => $client_secret,
    'grant_type' => 'refresh_token',
];

$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));

$response = curl_exec($ch);
curl_close($ch);

$token_data = json_decode($response, true);
$access_token = $token_data['access_token'];

$folder_id = isset($folder_id) ? $folder_id : null;

// Google Drive APIを使用してファイルリストを取得
if ($folder_id) {
    // フォルダIDが存在する場合、フォルダ内のファイルを取得
    $drive_url = 'https://www.googleapis.com/drive/v3/files?q=' . urlencode("'" . $folder_id . "' in parents");
} else {
    // フォルダIDが存在しない場合、全てのファイルを取得
    $drive_url = 'https://www.googleapis.com/drive/v3/files';
}

$ch = curl_init($drive_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $access_token,
]);

$response = curl_exec($ch);

if ($response === false) {
    echo 'Error: ' . curl_error($ch);
    curl_close($ch);
    exit();
}

curl_close($ch);

$file_list = json_decode($response, true);
if (isset($file_list['error'])) {
    echo 'Error: ' . $file_list['error']['message'];
    exit();
}

// ファイルリストを表示
foreach ($file_list['files'] as $file) {
    echo 'File ID: ' . $file['id'] . ' - File Name: ' . $file['name'] . PHP_EOL;
}
?> 
            

上記プログラムをSPIRAL内アクション>PHP実行に設置して実行してください。
実行結果にファイルIDとファイル名が記載されますので、File ID:の後のIDを控えてください。
$file_list['files']にファイルのリストが格納されています。
フォルダの絞り込み等を行いたい場合は
$drive_url = 'https://www.googleapis.com/drive/v3/files?q=' . urlencode("'" . $folder_id . "' in parents");

の様な形でAPIの接続先にパラメータを付与してリクエストを行ってください
パラメータの仕様については下記Google公式リファレンスをご確認ください。
Method: files.list
ファイルやフォルダを検索する
ステップ3 ファイルダウンロード及びSPIRALへアップロード

<?php
require_once "config.php";

//------------------------------
// 設定値
//------------------------------
define("API_URL", "https://api.spiral-platform.com/v1");
define("API_KEY", "");
define("APP_ROLE", "");
define("DB_ID", ""); //ファイルを格納するDBID
define("APP_ID", ""); //ファイルを格納するDBが属しているアプリID
$fileFieldId = "1"; //ファイルフィールドID
$fileFieldName = "file"; //ファイルフィールド識別名
$commonBase = CommonBase::getInstance();

$fileName = "image.png"; //アップロード時のファイル名
// ダウンロードするファイルIDを指定
$file_id = 'ステップ2で控えたFileIDを入力';

$token_url = 'https://oauth2.googleapis.com/token';
$post_fields = [
    'refresh_token' => $refresh_token,
    'client_id' => $client_id,
    'client_secret' => $client_secret,
    'grant_type' => 'refresh_token',
];

$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));

$response = curl_exec($ch);
curl_close($ch);

$token_data = json_decode($response, true);
$access_token = $token_data['access_token'];


$download_url = "https://www.googleapis.com/drive/v3/files/{$file_id}?alt=media";

// cURLでファイルをダウンロード
$ch = curl_init($download_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $access_token,
]);

$response = curl_exec($ch);

curl_close($ch);

//以下ダウンロードしたファイルをDBへ保存

    //ファイルアップロードトークン発行
    $apiUrlPass = "/apps/". APP_ID. "/dbs/". DB_ID. "/". $fileFieldId. "/files/uploadToken";
    $apiResponse = $commonBase->apiCurlAction("POST", $apiUrlPass);
    $fileUploadToken = $apiResponse["fileUploadToken"];
    //ファイルアップロード
    $apiUrlPass = "/apps/". APP_ID. "/dbs/". DB_ID. "/". $fileFieldId. "/files";

        // リクエストボディ(マルチパート形式)
        $requestBody = "--WebKitFormBoundary7MA4YWxkTrZu0gW\r\n";
        $requestBody .= "Content-Disposition: form-data; name=\"file\"; filename=\"". $fileName. "\"\r\n";
        $requestBody .= "Content-Type: image/png\r\n\r\n";
        $requestBody .= $response. "\r\n";
        $requestBody .= "--WebKitFormBoundary7MA4YWxkTrZu0gW\r\n";
        $requestBody .= "Content-Disposition: form-data; name=\"fileUploadToken\"\r\n\r\n";
        $requestBody .= $fileUploadToken. "\r\n";
        $requestBody .= "--WebKitFormBoundary7MA4YWxkTrZu0gW--";

        $contentType = "Content-Type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW";

    $apiResponse = $commonBase->apiCurlAction("POST", $apiUrlPass, $requestBody, $contentType);

// 登録するデータを指定

$insertData = array(
    $fileFieldName  => array($apiResponse["fileKey"]),
);

$resultRecordInsert = $commonBase->apiCurlAction("POST", "/apps/". APP_ID. "/dbs/". DB_ID. "/records", $insertData);

//------------------------------
// 共通モジュール
//------------------------------
class CommonBase {
    /**
     * シングルトンインスタンス
     * @var UserManager
     */
    protected static $singleton;

    public function __construct() {
        if (self::$singleton) {
            throw new Exception('must be singleton');
        }
        self::$singleton = $this;
    }
    /**
     * シングルトンインスタンスを返す
     * @return UserManager
     */
    public static function getInstance() {
        if (!self::$singleton) {
            return new CommonBase();
        } else {
            return self::$singleton;
        }
    }
    /**
     * V2用 API送信ロジック
     * @return Result
     */
    function apiCurlAction($method, $addUrlPass, $data = null, $multiPart = null, $jsonDecode = null) {
        $header = array(
            "Authorization:Bearer ". API_KEY,
            "X-Spiral-Api-Version: 1.1",
        );
        if($multiPart) {
            $header = array_merge($header, array($multiPart));
        } else {
            $header = array_merge($header, array("Content-Type:application/json"));
        }
        if(APP_ROLE){
			$header = array_merge($header, array("X-Spiral-App-Role: ".APP_ROLE));
		}
        // curl
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_URL, API_URL. $addUrlPass);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        if ($method == "POST") {
            if ($multiPart) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            } else {
                curl_setopt($curl, CURLOPT_POSTFIELDS , json_encode($data));
            }
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        }
        if ($method == "PATCH") {
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        }
        if ($method == "DELETE") {
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        }
        $response = curl_exec($curl);
        if (curl_errno($curl)) echo curl_error($curl);
        curl_close($curl);
        if($jsonDecode){
			return $response;
		}else{
            return json_decode($response, true);
		}
    }
}
?> 
            

上記プログラムをSPIRAL内アクション>PHP実行に設置して実行してください。
設定値をご自身の環境に合わせて修正してください。
$file_idにはステップ3で控えた値を入力してください。
修正が完了し、実行すると指定したファイルがSPIRALへアップロードされます。

その他

外部(Google)との連携になりますので、データの取扱や認証情報の取り扱いには十分お気をつけください。
特にクライアントIDやクライアントシークレット、認証キー等は他人に絶対に知られない様にしてください。
知られてしまうとGoogleアカウント上のデータが他人に操作、閲覧されてしまう可能性がございます。

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