You are right in that the drive quickstart guide is outdated, it refers to the old version of Google's PHP Client API Library that is on Google Code, rather than the newer one on GitHub. Hence the quickstart guide doesn't work with the PHP Client Library you downloaded. In addition, the quickstart guide code is intended to be executed in PHP command-line mode rather than on the server.
To answer the question, I've put in a few sub-answers:
- How to use the PHP Client Library
- How to pick a file with the Google Picker and get the file onto the server
Using the Google PHP Client Library with the Google Drive API
Try this page instead: https://developers.google.com/api-client-library/php/auth/web-app which has an example showing how to list files on a user's Google Drive using the new PHP library, including the whole OAuth procedure.
Unfortunately, even that is a bit outdated (the include path is outdated and is now deprecated). As such (and for StackOverflow's completeness sake) here's some code. I used a subdirectory drivetest in my web server root; change the URLs as necessary.
Do note that you need to get the client ID for "Web applications" in Google's Developer Console, and download the JSON (replacing the client_secrets.json
in the code as necessary).
drivetest/quickstart.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getItems();
echo json_encode($files_list);
} else {
$redirect_uri = 'http://localhost/drivetest/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
drivetest/oauth2callback.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivetest/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivetest/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
Use the Google File Picker to pick files
For your use case, you are probably better off using the Google Picker https://developers.google.com/picker/docs/ which implements the whole browse-and-select-file thing for you, and just gives an ID to the file. A summary of the steps required:
- Get access token (authentication)
- Use picker to let user pick file
- Use file ID returned from picker to get download URL
- Download file from download URL
We can do this in two ways (client-side or server-side):
Method 1: Client-side
Using this method, steps 1 - 3 are done in Javascript, and only step 4 is done in PHP. With this method we don't even need the PHP client library!
Here's an example (adapted from sample code in the above link and http://webdevrefinery.com/forums/topic/12931-dropbox-google-drive-file-pickers/):
picker.html
This file launches the filepicker upon page load and puts the URL into a form.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// The Client ID obtained from the Google Developers Console. Replace with your own Client ID.
var clientId = ""
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
// Scope to use to access user's Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.drive.files.get({
fileId: fileId
});
request.execute(processFile);
});
}
}
function processFile(file) {
var token = gapi.auth.getToken();
// console.log(file);
// console.log(token);
document.getElementById("fileurl").value = file.downloadUrl+"&access_token="+token.access_token;
}
</script>
</head>
<body>
<form action="submit.php" method="post">
<label for="fileurl">File Download URL</label><input type="text" name="fileurl" id="fileurl">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
We then submit the form to a PHP script to download the file on the server. The trick here is that we also need to pass the access token from the client to the server, since the user is not authenticated on the server side. Surprisingly, you can simply append the access_token
parameter to authenticate the download of the file, as shown above.
submit.php
Use file_get_contents
or CURL, depending on what your server supports. HTTPS support is required for this to work though.
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Should verify in production!
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
//echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
A more official way (following https://developers.google.com/drive/web/manage-downloads#alternate_method_using_downloadurl) is to send the authorization token separately using the Authorization
header. Modify the Javascript above to send the download URL and token separately, then use something like the code below instead. If you want to use file_get_contents
, see PHP file_get_contents() and headers on how to send custom headers. Note that you need to have the Bearer
word before the token!
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$_POST['authtoken']));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
Method 2: Server-side (using PHP)
Using this method, steps 1, 3 and 4 are done in PHP, and only step 2 is done in Javascript.
quickstart.php
This page checks if there is an access token in the session, if there is not it redirects the user for authentication. If there is, it shows the picker and a form. In the picker Javascript code, note that the oAuthToken used is obtained with PHP from the server! Source: Use Google Picker without logging in with Google account (with OAuth). The form then submits a POST request to this page and the file is downloaded.
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
// Ref: https://developers.google.com/drive/v2/reference/files/get
function downloadFile($service, $file) {
$downloadUrl = $file->getDownloadUrl();
if ($downloadUrl) {
$request = new Google_Http_Request($downloadUrl, 'GET', null, null);
$httpRequest = $service->getClient()->getAuth()->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200) {
return $httpRequest->getResponseBody();
} else {
// An error occurred.
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
if (isset($_POST['fileid'])){
$drive_service = new Google_Service_Drive($client);
$file = $drive_service->files->get($_POST['fileid']);
$data = downloadFile($drive_service, $file);
file_put_contents('temp.jpg', $data);
echo "file uploaded";
exit();
}
} else {
$redirect_uri = 'http://localhost/drivepicker-php/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
exit();
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
var pickerApiLoaded = false;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken('<?= json_decode($client->getAccessToken())->access_token; ?>')
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
document.getElementById("fileid").value = fileId;
}
}
</script>
</head>
<body>
<form action="quickstart.php" method="post">
<label for="fileid">File ID</label><input type="text" name="fileid" id="fileid">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
oauth2callback.php
Helper file for the OAuth callback.
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivepicker-php/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (!isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivepicker-php/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>