【PHP】フォームでファイルをGoogle Driveに アップロードする方法 (GoogleDrive API 使用)
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
参考にしていただければ幸いです!
ディスカッション
コメント一覧
参考にさせていただきました、ありがとうございます!
ただ「PHPファイルの作成」の項で1点だけ。
77行目の $client が未定義でした。
直前に $client = getClient(); を入れれば当方の環境でも
正常に動作しましたのでご報告です。
※「2021年8月23日更新の最小構成版はこちらから」の
ページには $client = getClient(); の記述がありましたので、
何かで間違って消えてしまったのかなと。
ご指摘ありがとうございます!
修正させていただきました!