【PHP】PHPでGoogleDriveにファイルをアップロードするテンプレート(2021年8月23日)

2021年8月23日

フォームからファイルをGoogleDriveにアップロードするためのテンプレートです。「Google Drive Client PHP」を利用しますのでインストールをしていきます。最小構成になっていますので、動作することが確認できましたら、機能を追加してみてください。

省略前のコードにつきましてはこちらを御覧ください

必要なもの

  • クライアント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ファイルがダウンロードできますので「client_id.inc」という名前で保存してください。


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

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

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

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

実際に送るURL

redirect_uriにつきましては今回は「http://localhost」でOKです。

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が返ってくるのでコピーして「access-token.inc」という名前で保存をします。

ファイルの構成

ファイルの構成は下記のようになります。srcフォルダはダウンロードでのインストール時のみ必要です。

FormTest/
     ├PHP/
     │   ├vender/
     │   ├(src/)
     │   └ uploaddrive.php
     ├json/
     │    ├ access-token.inc
     │    └ client_id.inc
     │
     └index.php

Google Drive Client PHPのインストール


GoogleAPIを使用するために、Google Drive Client PHPライブラリーをインストールします。インストールする方法はcomposerを使用する方法とファイルをダウンロードしてフォルダに入れる方法があります。

①composer使う場合

ターミナルでPHPフォルダで下記を実行します。

composer require google/apiclient:^2.10

「vender」というフォルダが生成されれば成功です。

②ダウンロードする場合

ここのreleasesからダウンロードします。解凍して「vendor」と「src」を「PHP」フォルダに入れます。

PHPファイルの作成(uploaddrive.php)

下記をコピペして「uploaddrive.php」ファイルを作成してください。アップロード先のフォルダIDと共有フォルダの場合は共有フォルダのルートファイルIDを入力してください。共有フォルダへのアップロードについてはこちらを御覧ください。

<?php

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

/************************************************/
/* uploaddrive.php                      */
/* FolderId : アップロード先のフォルダ名         */
/* DriveId  : 共有フォルダのファイルパス       */
define('FolderId', '1xX8gBw7r5nPa-*************');
define('DriveId' , '0AHbLJ**************',);

/* Load previously authorized credentials path. */
define('CREDENTIALS_PATH', __DIR__ . '/json/access-token.inc');
define('CLIENT_SECRET_PATH', __DIR__ . '/json/client_id.inc');

/************************************************/ 

require_once __DIR__ . '/vendor/autoload.php';
define('APPLICATION_NAME', 'DBBackup');

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

$error = "";

/**
 * 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');
    $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()) {
        $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($files,$folderName,$namestr){
    //フォルダーIDの設定
    
    $folderId= FolderId;
    $filePaths = $files["file"]["tmp_name"];
    $client = getClient();  
      
    $driveService = new Google\Service\Drive($client);
    $error="";
    
    try{
        // フォルダを新規作成する
        $fileData = array();
        $fileData['name'] = $folderName;
        $fileData['mimeType'] = 'application/vnd.google-apps.folder';    
        $fileData['parents'][] = $folderId;
    
        $fileMetadata = new Google\Service\Drive\DriveFile($fileData);

        $file = $driveService->files->create($fileMetadata,array(
            'fields'=>'id,name,parents',
            "supportsTeamDrives" => true,
        ));

        $createfolderId = $file->id;
    } catch (Google_Service_Exception $e) {
        $error .=$e->getMessage();
    } catch (\Google_Exception $e) {
        $error .=$e->getMessage();
    }
    
    $count=count($filePaths);
    for ($i = 0; $i < $count ; ++$i){
    
        $createfileName = $namestr.pathinfo($_FILES["file"]["name"][$i], PATHINFO_EXTENSION);
       // アップロードするGoogle DriveのフォルダのIDとファイル名を指定する
        $fileMetadata = new Google\Service\Drive\DriveFile(array(
                        'name' =>  $createfileName,
                        'DriveId' => DriveId,
                        'teamDriveId' => DriveId,
                        'parents' => array($createfolderId),
                        "includeTeamDriveItems" => true,
                        "supportsTeamDrives" => true,
                ));
                
    // アップロードするファイルのMIMEタイプを取得する

        $mime = mime_content_type($filePaths[$i]);
        
        try {
            $content = file_get_contents($filePaths[$i]);
            $file = $driveService->files->create($fileMetadata, array(
                    'data' => $content,
                    'mimeType' => $mime,
                    'uploadType' => 'multipart',
                    "supportsTeamDrives" => true,
                    'fields' => 'id',
            ));
            
            // print "File '$fileName' uploaded with id '$file->id'" . PHP_EOL;
        }
        catch (Exception $exc) {
            $error .= "Error working with file '$createfileName':" . $exc->getMessage();
        }
    }
    $message = array(
        "folderID"=>$createfolderId,
        "error"=>$error,
    );
    return $message;
}

フォームの作成(index.php)

<!DOCTYPE html>

<?php
ini_set('log_errors','on');
//エラーレベルを設定
ini_set('error_reporting', E_ALL);
//ログの出力ファイルを指定
ini_set('error_log','php.log');

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    require_once __DIR__ . '/php/uploaddrive.php';
    uploadFile($_FILES,"フォルダ名","TEST");
    echo '<div class="m-2 alert alert-success" role="alert">送信完了</div>';
}
?>

<html lamg="ja">
<head>
    <meta charset="UTF-8">
    <title>ファイル送信</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" 
    integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
</head>

<body>
    <div class="container">
        <h1>ファイル送信</h1>
        <form class="needs-validation" action="" method="POST" enctype="multipart/form-data">
            <div class="formBox">
                <input type="hidden" name="MAX_FILE_SIZE" value="6000000000000" />
                <input type="file" class="form-control" id="file1" name="file[]" >            
                <button type="submit" class="btn btn-primary btn-block mt-3">送信</button>
            </div>
        </form>
    </div>
</body>
</html>

上記のフォームからファイル送信をすると、「送信完了」と表示され、GoogleDriveのフォルダにファイルのアップロードができていると思います。

ファイルの送信ができない場合

ファイルの送信ができない場合、「php.log」というファイルを確認します。

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

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

GCP,PHP

Posted by Next-k