【PHP】フォームでファイルをGoogle Driveに アップロードする方法 (GoogleDrive API 使用)

2021年3月17日

8月23日更新の最小構成版はこちらから

HTMLでフォームを作成する際に、サーバーを使わずにGoogleスプレッドシートとGoogleドライブにファイルを保管することが増えてきました。今回はPHPでGoogleドライブにアップロードする方法になります。これを活用すればフォームからアップロードされたファイルをGoogleドライブに保存することができます。ファイルを送信するフォームの作成についてはこちらを御覧ください。

必要なもの

  • クライアントIDのJSONファイル
  • 認証後トークンのJSONファイル

クライアントIDのJSONファイルの作成

GoogleAPI の認証情報の作成をします。

https://console.cloud.google.com/apis/dashboard

認証情報の作成 → ウィザードで選択

使用するAPI → Google Drive APIを選択

APIを呼び出す場所 → ウェブサーバー

アクセスするデータの種類 → ユーザーデータ

を選択する。

OAuth同意画面の設定が必要であれば

アプリ名 → 任意

ユーザーサポートメール → 任意のメールアドレス

デベロッパーの連絡先情報 → 任意のメールアドレス

スコープの設定 → 必要なスコープを選択

上記で設定する。

OAuth 2.0 クライアント IDが作成できたら、クライアントIDのJSONファイルがダウンロードできる。


認証後トークンのJSONファイルの作成

クライアントIDのJSONファイルのデータを使用します。

以下のURLにクエリパラメータを追加してブラウザでアクセスする
https://accounts.google.com/o/oauth2/auth

https://accounts.google.com/o/oauth2/auth
?client_id=[4で取得したクライアントID]
&redirect_uri=[4で設定したリダイレクトURI]
&scope=https://www.googleapis.com/auth/drive (使用したいサービスのAPIにスコープする。今回はGoogleドライブ)
&response_type=code (認証をコードとして出力)
&approval_prompt=force (認証をスキップしない)
&access_type=offline (オフラインでAPIを使用=リフレッシュキーを発行)

実際に送るURL

https://accounts.google.com/o/oauth2/auth
?client_id=343******************************ggso1d8.apps.googleusercontent.com
&redirect_uri=http://localhost
&scope=https://www.googleapis.com/auth/drive
&response_type=code
&approval_prompt=force
&access_type=offline

上記のURLをブラウザに入力しENTERを押す。

下記の画面がでるので「許可をクリック」する。

「このサイトにアクセスできません」と表示がされるが、URLにコード値が返ってきているのでcode=以下をコピー

ターミナルなどで下記コードを実行する。「”」などはいらない。

curl -d client_id=[クライアントID] -d client_secret=[クライアントシークレット] -d redirect_uri=[リダイレクトURI] -d grant_type=authorization_code -d code=[認証コード] https://accounts.google.com/o/oauth2/token

上記を実行すると認証後のJSONが返ってくるのでコピーして保存をする。


PHPファイルの作成

Googleクライアントライブラリをインストールはされていることを前提とします。

インストールしていない場合は前の記事を参照してください。

<?php


//ファイルのアップロード

require_once __DIR__ . '/vendor/autoload.php';
define('APPLICATION_NAME', 'Drive API PHP Quickstart'); #任意の名前
define('CREDENTIALS_PATH', '~/.credentials/drive-php-quickstart.json'); #認証後のtokenファイルを格納する場所(任意)
define('CLIENT_SECRET_PATH', 'client_secret.json'); #ダウンロードしてきたjsonファイル

// ScopeをDRIVE_FILEに設定する
define('SCOPES', implode(' ', array(
    Google_Service_Drive::DRIVE)
));



 
/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient() {
    $client = new Google_Client();
    $client->setApplicationName(APPLICATION_NAME);
    $client->setScopes(SCOPES);
    $client->setAuthConfig(CLIENT_SECRET_PATH);
    $client->setAccessType('offline');
    // Load previously authorized credentials from a file.
    //echo CREDENTIALS_PATH;
    $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
    $accessToken = json_decode(file_get_contents($credentialsPath), true);
 
    $client->setAccessToken($accessToken);
 
    // Refresh the token if it's expired.
    if ($client->isAccessTokenExpired()) {
      //print "expired==>\n";
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
    }
    return $client;
}
 
 
/**
 * Expands the home directory alias '~' to the full path.
 * @param string $path the path to expand.
 * @return string the expanded path.
 */
function expandHomeDirectory($path) {
    $homeDirectory = getenv('HOME');
    if (empty($homeDirectory)) {
        $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
    }
    return str_replace('~', realpath($homeDirectory), $path);
}



function uploadFile($filePath,$folderName){

    printf("=============================================\n");
    printf("Start Script:%s\n", date("Y-m-d h:m:s"));
    printf("Save FilePath To Google Drive=>%s\n", $filePath);
    printf("Save Folder In Google Drive=>%s\n", $folderName);
    
    if (file_exists($filePath)) {
    } else {
        die("$filepath は存在しません");
        exit();
    }
    
    $path_parts = pathinfo($filePath);
    $fileName = $path_parts['basename'];
    $client = getClient();
    $driveService = new Google_Service_Drive($client);
    
    // Google DriveのフォルダIDを取得
    $result = $driveService->files->listFiles(array(
            'q' => "mimeType='application/vnd.google-apps.folder'",
            'q' => "name='$folderName'",
        ));
    $folderId = "";
    
    foreach ( $result->getFiles() as $file) {
        assert($file instanceof \Google_Service_Drive_DriveFile);
        $name = $file->name;
        if ($name == $folderName){
        $folderId = $file->id;
        break;
        }
    }
    
    if ($folderId == ""){
    try{
        // フォルダが存在しなければフォルダを新規作成する
        $fileData = array();
        $fileData['name'] = $folderName;
        $fileData['mimeType'] = 'application/vnd.google-apps.folder';
    
        // ここではroot直下に作成、 ここで親フォルダのIDを指定すれば、そこの配下に作れる
        $fileData['parents'][] = 'root';
    
        $fileMetadata = new Google_Service_Drive_DriveFile($fileData);
        $file = $driveService->files->create($fileMetadata,['fields'=>'id,name,parents']);
        $folderId = $file->id;
        printf("New Folder Created: ID:%s Name:%s parent ID:%s", $file->id, $file->name, $file->parents[0]);
    } catch (Google_Service_Exception $e) {
        print $e->getMessage();
    
    } catch (\Google_Exception $e) {
        print $e->getMessage();
    }
    }
    
    // アップロードするGoogle DriveのフォルダのIDを指定する
    $fileMetadata = new Google_Service_Drive_DriveFile(array(
                    'name' => $fileName,
                    'parents' => array($folderId)
            ));
    
    // アップロードするファイルのMIMEタイプを取得する
    $mime = mime_content_type($filePath);
    
    try {
        $content = file_get_contents($filePath);
        $file = $driveService->files->create($fileMetadata, array(
                'data' => $content,
            'mimeType' => $mime,
    //          'mimeType' => 'application/x-gzip',
                'uploadType' => 'multipart',
                'fields' => 'id'));
        print "File '$fileName' uploaded with id '$file->id'" . PHP_EOL;
    }
    catch (Exception $exc) {
        print "Error working with file '$fileName':" . $exc->getMessage();
    }
}

下記を実行するとGドライブにアップロードされます。

uploadFile("アップロードしたいファイルのパス",”Gドライブのフォルダ名”)

使用方法はこちらの記事でもご覧いただけます。

共有フォルダの場合

共有フォルダを指定する場合は「404 親ファイルが見つかりませんエラー」が出るので、この記事を参考にしてください。

【PHP】Google Drive API 共有フォルダの場合

ファイル送信でエラーが発生する場合

Your Composer dependencies require a PHP version “>= 8.0.0"

Parse error: syntax error, unexpected '|’, expecting variable

ここのサイトを参考にすると上記のエラーはpsr / cacheがphp8以上対応になっているからのようです。そのため下記を実行してpsr / cacheのバージョンを下げる必要があります。

composer.jsonの修正

composer.jsonに「"psr/cache": “^1.0″」を追加します。

{
    "require": {
        "google/apiclient": "^2.10",
        "psr/cache": "^1.0"
    }
}

ターミナルで下記を実行

composer update

参考にしていただければ幸いです!

2021年8月23日更新の最小構成版はこちらから

GCP,PHP

Posted by Next-k