I am trying to set up a cron job that will back up various files from my server to Google Drive. I have looked at many solutions and none seem to work! The closest I have got (using oAuth) is this:
<?php
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once __DIR__ . '/../vendor/autoload.php';
require_once "base.php";
echo pageHeader("File Upload - Uploading a large file");
/*************************************************
* Ensure you've downloaded your oauth credentials
************************************************/
if (!$oauth_credentials = getOAuthCredentialsFile()) {
echo missingOAuth2CredentialsWarning();
return;
}
/************************************************
* The redirect URI is to the current page, e.g:
* http://localhost:8080/large-file-upload.php
************************************************/
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
echo "<br>$redirect_uri";
$client = new Google_Client();
echo "<br>got client";
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/drive");
$service = new Google_Service_Drive($client);
// add "?logout" to the URL to remove a token from the session
if (isset($_REQUEST['logout'])) {
unset($_SESSION['upload_token']);
}
echo "<br>got service";
/************************************************
* If we have a code back from the OAuth 2.0 flow,
* we need to exchange that with the
* Google_Client::fetchAccessTokenWithAuthCode()
* function. We store the resultant access token
* bundle in the session, and redirect to ourself.
************************************************/
if (isset($_GET['code'])) {
echo "<br>getting token";
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
echo "<br>Got token";
$client->setAccessToken($token);
// store in the session also
$_SESSION['upload_token'] = $token;
// redirect back to the example
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
// set the access token as part of the client
if (!empty($_SESSION['upload_token'])) {
echo "<br>getting access token";
$client->setAccessToken($_SESSION['upload_token']);
if ($client->isAccessTokenExpired()) {
unset($_SESSION['upload_token']);
}
} else {
$authUrl = $client->createAuthUrl();
}
echo "<br>Ready to go";
/************************************************
* If we're signed in then lets try to upload our
* file.
************************************************/
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $client->getAccessToken()) {
/************************************************
* We'll setup an empty 20MB file to upload.
************************************************/
DEFINE("TESTFILE", 'testfile.txt');
if (!file_exists(TESTFILE)) {
$fh = fopen(TESTFILE, 'w');
fseek($fh, 1024*1024*20);
fwrite($fh, "!", 1);
fclose($fh);
}
$file = new Google_Service_Drive_DriveFile();
$file->name = "Big File";
$chunkSizeBytes = 1 * 1024 * 1024;
echo "<br>created file";
// Call the API with the media upload, defer so it doesn't immediately return.
$client->setDefer(true);
$request = $service->files->create($file);
// Create a media file upload to represent our upload process.
$media = new Google_Http_MediaFileUpload(
$client,
$request,
'text/plain',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize(TESTFILE));
echo "<br>created media";
// Upload the various chunks. $status will be false until the process is
// complete.
$status = false;
$handle = fopen(TESTFILE, "rb");
while (!$status && !feof($handle)) {
// read until you get $chunkSizeBytes from TESTFILE
// fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
// An example of a read buffered file is when reading from a URL
$chunk = readVideoChunk($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
// The final value of $status will be the data from the API for the object
// that has been uploaded.
$result = false;
if ($status != false) {
$result = $status;
}
fclose($handle);
}
function readVideoChunk ($handle, $chunkSize)
{
$byteCount = 0;
$giantChunk = "";
while (!feof($handle)) {
// fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
$chunk = fread($handle, 8192);
$byteCount += strlen($chunk);
$giantChunk .= $chunk;
if ($byteCount >= $chunkSize)
{
return $giantChunk;
}
}
return $giantChunk;
}
?>
<div class="box">
<?php if (isset($authUrl)): ?>
<div class="request">
<a class='login' href='<?= $authUrl ?>'>Connect Me!</a>
</div>
<?php elseif($_SERVER['REQUEST_METHOD'] == 'POST'): ?>
<div class="shortened">
<p>Your call was successful! Check your drive for this file:</p>
<p><?= $result->name ?></p>
<p>Now try downloading a large file from Drive.
</div>
<?php else: ?>
<form method="POST">
<input type="submit" value="Click here to upload a large (20MB) test file" />
</form>
<?php endif ?>
</div>
<?= pageFooter(__FILE__) ?>
But it seems to get as far as the "Getting token" comment and stops - have poked around in the Google API code with more tracing but surely I should not need to do this?
Yes I have oauth credentials set up for this - gets past them
You should consider using a service account if you are working with a cron job which will need to be run without user intervention.
Just note that a service account is a dummy user files uploaded by the service account will be owned by the service account you will need to set the service account up to grant your personal account permissions on the files it uploads.
Also files will be uploaded to the service accounts drive account unless you give it permissions to write to a directory on your personal drive account and upload to that instead.
// Load the Google API PHP Client Library.
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
return getServiceAccountClient();
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
* Scopes will need to be changed depending upon the API's being accessed.
* array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope([YOUR SCOPES HERE]);
return $client;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Related
How to update access token (with the help refresh token) and upload video on YouTube?
authenticate.php
<?php
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https' : 'http';
$redirect = filter_var($protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
exit;
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
config.php
<?php
require_once 'google-api-php-client-2.2.0/vendor/autoload.php';
// Call set_include_path() as needed to point to your client library.
// require_once 'Google/Client.php';
// require_once 'Google/Service/YouTube.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* Google Developers Console <https://console.developers.google.com/>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = '';
$OAUTH2_CLIENT_SECRET = '';
require_once 'inc/authenticate.php';
upload.php
<?php
if (!empty($_POST['video_path'])) {
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = $_POST['video_path'];
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
if (!empty($_POST['video_title'])) {
$snippet->setTitle($_POST['video_title']);
}
if (!empty($_POST['video_description'])) {
$snippet->setDescription($_POST['video_description']);
}
if (!empty($_POST['video_tags'])) {
$video_tags = array_filter(array_map('trim', explode(',', $_POST['video_tags'])));
$snippet->setTags($video_tags);
}
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
// $snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
if (!empty($_POST['video_status']) && in_array($_POST['video_status'], array('public', 'private', 'unlisted'))) {
$status->privacyStatus = $_POST['video_status'];
}
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert('status,snippet', $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
// $media->setFileSize(filesize($videoPath));
$headers = array_change_key_case(get_headers($videoPath, true));
$media->setFileSize(intval($headers['content-length']));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, 'rb');
while (!$status && !feof($handle)) {
$chunk = stream_get_contents($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$video_url = 'https://www.youtube.com/watch?v=' . $status['id'];
?>
<div class="alert alert-success">
<h3 class="alert-heading">Video Uploaded</h3>
<p><?php echo $video_url; ?></p>
</div>
<?php
} catch (Google_Service_Exception $e) {
?>
<div class="alert alert-danger">
<p>A service error occurred: <code><?php echo htmlspecialchars($e->getMessage()); ?></code></p>
</div>
<?php
} catch (Google_Exception $e) {
?>
<div class="alert alert-danger">
<p>An client error occurred: <code><?php echo htmlspecialchars($e->getMessage()); ?></code></p>
</div>
<?php
}
$_SESSION['token'] = $client->getAccessToken();
}
youtube-uploader
How to add refresh_token file, to prevent authorization from being reset.
{"access_token":"ya29.GluQBs6GFi_0sG1VgmLUZ0....","expires_in":3600,"refresh_token":"1\/cLxr6ox0...","scope":"https:\/\/www.googleapis.com\/auth\/userinfo.email https:\/\/www.googleapis.com\/auth\/userinfo.profile","token_type":"Bearer","id_token":"eyJhbGc..","created":1547330141}
I found the right information but could not implement it in the code above.
PHP server-side YouTube V3 OAuth API video upload guide
Russian info and code "[Examples] Authorization (getting the access and refresh token) OAuth 2.0 with Google and work with Google API in PHP"
I can get the refresh token and save everything to a file or session, but how can I integrate the verification and update of the token into the code above?
Help me please!
I am running a WordPress site with ffmpeg where I allow users to create videos using a form. The videos work fine and are saved in their own directories per post.
I am now trying to allow users to upload the videos they created, to their own youtube channel.
Using PHP code from youtube api, and my app from google console, I am able to successfully upload a video to my own account. And it only asks for me to authenticate once.
PHP Code --
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/vendor/autoload.php';
$key = file_get_contents('the_key.txt');
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/');
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/YouTube.php';
$application_name = 'youtube4true';
$OAUTH2_CLIENT_ID = 'REMOVED FOR STACK';
$OAUTH2_CLIENT_SECRET = 'REMOVED FOR STACK';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
$refresh_token = $_SESSION[$tokenSessionKey]['refresh_token'];
file_put_contents('the_key.txt', $refresh_token);
} elseif(file_exists('the_key.txt')) {
$refresh_token = file_get_contents('the_key.txt');
$client->refreshToken($refresh_token);
$_SESSION['token'] = $client->getAccessToken();
$access_token = $_SESSION['token']['access_token'];
$client->setAccessToken($access_token);
$refresh_token = $_SESSION['token']['refresh_token'];
file_put_contents('the_key.txt', $refresh_token);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = "HERE I WILL USE AJAX TO PASS THE PATH TO THE VIDEO FILE";
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("tag1", "tag2"));
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "public";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
// Call the channels.list method to retrieve information about the
// currently authenticated user's channel.
$channelsResponse = $youtube->channels->listChannels('contentDetails', array(
'mine' => 'true',
));
$htmlBody = '';
foreach ($channelsResponse['items'] as $channel) {
// Extract the unique playlist ID that identifies the list of videos
// uploaded to the channel, and then call the playlistItems.list method
// to retrieve that list.
$uploadsListId = $channel['contentDetails']['relatedPlaylists']['uploads'];
$playlistItemsResponse = $youtube->playlistItems->listPlaylistItems('snippet', array(
'playlistId' => $uploadsListId,
'maxResults' => 50
));
$htmlBody .= "<h3>Videos in list $uploadsListId</h3><ul>";
foreach ($playlistItemsResponse['items'] as $playlistItem) {
$htmlBody .= sprintf('<li>%s (%s)</li>', $playlistItem['snippet']['title'],
$playlistItem['snippet']['resourceId']['videoId']);
}
$htmlBody .= '</ul>';
}
} catch (Google_ServiceException $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION['token'] = $client->getAccessToken();
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorise access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Video Uploaded</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
I've also successfully been able to follow to javascript example to upload from my computer, but the files are stored on the server so that's not what I want.
With javascript, getting a new token for users seems to work, except the file upload issue and that users have to go into their Google accounts to revoke access/log out from my site app.
JS Code -
/*
Copyright 2015 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
*/
var signinCallback = function (result){
if(result.access_token) {
var uploadVideo = new UploadVideo();
uploadVideo.ready(result.access_token);
}
};
var STATUS_POLLING_INTERVAL_MILLIS = 60 * 1000; // One minute.
/**
* YouTube video uploader class
*
* #constructor
*/
var UploadVideo = function() {
/**
* The array of tags for the new YouTube video.
*
* #attribute tags
* #type Array.<string>
* #default ['google-cors-upload']
*/
this.tags = ['test'];
/**
* The numeric YouTube
* [category id](https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.videoCategories.list?part=snippet®ionCode=us).
*
* #attribute categoryId
* #type number
* #default 22
*/
this.categoryId = 22;
/**
* The id of the new video.
*
* #attribute videoId
* #type string
* #default ''
*/
this.videoId = '';
this.uploadStartTime = 0;
};
UploadVideo.prototype.ready = function(accessToken) {
this.accessToken = accessToken;
this.gapi = gapi;
this.authenticated = true;
this.gapi.client.request({
path: '/youtube/v3/channels',
params: {
part: 'snippet',
mine: true
},
callback: function(response) {
if (response.error) {
console.log(response.error.message);
} else {
$('#channel-name').text(response.items[0].snippet.title);
$('#channel-thumbnail').attr('src', response.items[0].snippet.thumbnails.default.url);
$('.pre-sign-in').hide();
$('.post-sign-in').show();
}
}.bind(this)
});
$('#button').on("click", this.handleUploadClicked.bind(this));
};
/**
* Uploads a video file to YouTube.
*
* #method uploadFile
* #param {object} file File object corresponding to the video to upload.
*/
UploadVideo.prototype.uploadFile = function(file) {
var metadata = {
snippet: {
title: $('#title').val(),
description: $('#description').text(),
tags: this.tags,
categoryId: this.categoryId
},
status: {
privacyStatus: $('#privacy-status option:selected').text()
}
};
var uploader = new MediaUploader({
baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
file: file,
token: this.accessToken,
metadata: metadata,
params: {
part: Object.keys(metadata).join(',')
},
onError: function(data) {
var message = data;
// Assuming the error is raised by the YouTube API, data will be
// a JSON string with error.message set. That may not be the
// only time onError will be raised, though.
try {
var errorResponse = JSON.parse(data);
message = errorResponse.error.message;
} finally {
alert(message);
}
}.bind(this),
onProgress: function(data) {
var currentTime = Date.now();
var bytesUploaded = data.loaded;
var totalBytes = data.total;
// The times are in millis, so we need to divide by 1000 to get seconds.
var bytesPerSecond = bytesUploaded / ((currentTime - this.uploadStartTime) / 1000);
var estimatedSecondsRemaining = (totalBytes - bytesUploaded) / bytesPerSecond;
var percentageComplete = (bytesUploaded * 100) / totalBytes;
$('#upload-progress').attr({
value: bytesUploaded,
max: totalBytes
});
$('#percent-transferred').text(percentageComplete);
$('#bytes-transferred').text(bytesUploaded);
$('#total-bytes').text(totalBytes);
$('.during-upload').show();
}.bind(this),
onComplete: function(data) {
var uploadResponse = JSON.parse(data);
this.videoId = uploadResponse.id;
$('#video-id').text(this.videoId);
$('.post-upload').show();
this.pollForVideoStatus();
}.bind(this)
});
// This won't correspond to the *exact* start of the upload, but it should be close enough.
this.uploadStartTime = Date.now();
uploader.upload();
};
UploadVideo.prototype.handleUploadClicked = function() {
$('#button').attr('disabled', true);
this.uploadFile($('#file').get(0).files[0]);
};
UploadVideo.prototype.pollForVideoStatus = function() {
this.gapi.client.request({
path: '/youtube/v3/videos',
params: {
part: 'status,player',
id: this.videoId
},
callback: function(response) {
if (response.error) {
// The status polling failed.
console.log(response.error.message);
setTimeout(this.pollForVideoStatus.bind(this), STATUS_POLLING_INTERVAL_MILLIS);
} else {
var uploadStatus = response.items[0].status.uploadStatus;
switch (uploadStatus) {
// This is a non-final status, so we need to poll again.
case 'uploaded':
$('#post-upload-status').append('<li>Upload status: ' + uploadStatus + '</li>');
setTimeout(this.pollForVideoStatus.bind(this), STATUS_POLLING_INTERVAL_MILLIS);
break;
// The video was successfully transcoded and is available.
case 'processed':
$('#player').append(response.items[0].player.embedHtml);
$('#post-upload-status').append('<li>Final status.</li>');
break;
// All other statuses indicate a permanent transcoding failure.
default:
$('#post-upload-status').append('<li>Transcoding failed.</li>');
break;
}
}
}.bind(this)
});
};
I'm pretty sure it has to do with the refresh or access token. So how can I create an access token for each user instead of only allowing my account on the app?
You need to perform the OAUTH dance
Google has some good documentation on the process. The following quoted content and code is pulled from that site.
Your application identifies the permissions it needs.
Your application redirects the user to Google along with the list of requested permissions.
The user decides whether to grant the permissions to your application.
Your application finds out what the user decided.
If the user granted the requested permissions, your application retrieves tokens needed to make API requests on the user's behalf.
Code for steps 1 and 2:
// setup client (step.1)
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_UPLOAD);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->setAccessType('offline'); // offline access
$client->setIncludeGrantedScopes(true); // incremental auth
// get url and redirect (step.2)
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
exit();
You'll need to setup your redirect url to accept the return call from them in the format something like:
[your_callback_url]/oauth2callback?state=state_parameter_passthrough_value&code=[code]&scope=[scope]
Then you extract the details from the callback and swap them for a token which will allow you to upload.
// swap the code for a token (step.5)
// … do client setup first
// then auth with the code
$client->authenticate($_GET['code']);
// retrieve the token
$access_token = $client->getAccessToken();
You can then use that token in your api calls to make calls on behalf of the user.
There is also a complete example on that same page.
I was able to get it working the way I wanted by using the following form on my page -
<form id="publish-youtube" action="/path/to/upload.php" method="post" target="_blank">
<input type="hidden" id="a_id" name="a_id" value="<?php echo $post_author_id; ?>" />
<input type="hidden" id="vid_id" name="vid_id" value="<?php echo $v_Id; ?>" />
<input type="submit" id="ytu_submit" name="ytu_submit" value="Publish to YouTube">
</form>
Then I followed the youtube api docs to create my app and my upload.php script, which asks the user to sign in if not already and it uploads the video based on the values from the form ( Note: Im using wordpress ) --
<?php
//require_once $_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/vendor/autoload.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/gap/google-api-php-client/');
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/YouTube.php';
session_start();
$application_name = 'XXXX';
$OAUTH2_CLIENT_ID = 'XXXX';
$OAUTH2_CLIENT_SECRET = 'XXXX';
$videoTitle = $_POST['titlez'];
$authorID = $_POST['a_id'];
$vidID = $_POST['vid_id'];
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
get_header();
global $current_user, $imic_options; // Use global
get_currentuserinfo(); // Make sure global is set, if not set it.
if ((user_can($current_user, "administrator"))||(user_can($current_user, "edit_others_posts")) ):
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = $_SERVER["DOCUMENT_ROOT"] ."/uploads/".$authorID."/".$vidID."/output-".$vidID.".mp4";
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("tag1", "tag2"));
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "public";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$htmlBody .= "<h3>Video Uploaded</h3><ul>";
$htmlBody .= sprintf('<li>%s</li>',
$status['snippet']['title']);
$htmlBody .= sprintf('<li>Video Link</li>',
$status['id']);
$htmlBody .= '</ul>';
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == '(I never changed this)REPLACE_ME') {
$htmlBody = <<<END
<h3>Client Credentials Required</h3>
<p>
You need to set <code>\$OAUTH2_CLIENT_ID</code> and
<code>\$OAUTH2_CLIENT_ID</code> before proceeding.
<p>
END;
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
?>
<div id="ytu-container">
<?=$htmlBody?>
</div>
<?php
else: echo imic_unidentified_agent();
endif;
get_footer();
?>
Currently working with AWS with laravel 5, Need to add google drive to my laravel project, how to connect to google drive to upload and view files for users.
I am tried following sample but getting login required error. how to get access_token before upload file?
$client = new Google_Client();
$client->setClientId('abc.apps.googleusercontent.com');
$client->setClientSecret('abc');
$client->setRedirectUri('abc');
$client->setScopes(array('https://www.googleapis.com/auth/drive.file'));
if (isset($_GET['code']) || (isset($_SESSION['access_token']) && $_SESSION['access_token']))
{
if (isset($_GET['code'])){
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
}
else
$client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Drive($client);
$file = new Google_Service_Drive_DriveFile();
$file->setDescription('image');
$file->setMimeType('image/png');
$data = file_get_contents(public_path('images\log.png');
$createdFile = $service->files->create($file, array(
'data' => $data,
'mimeType' => 'image/png',
'uploadType' => 'multipart'
));
return $createdFile;
} else {
$authUrl = $client->createAuthUrl();
header('Location: ' . $authUrl);
exit();
}
Use google service account to avoid login or access token.
attache service account json file to google client API (create key in service account page)
upload file to google drive and get file id
use file id to access your file in the browser
Example :
Using two functions to create and view file
public function uploadTogoogleDrive(){
$client = new Google_Client();
$client->setAuthConfig(public_path('service_account.json'));
$client->setScopes(array('https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.file'));
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
$service = new Google_Service_Drive($client);
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'DefaltReport.pdf'));
$content = file_get_contents(public_path('reports\DefaltReport.pdf'));
$file = $service->files->create($fileMetadata, array(
'data' => $content,
'mimeType' => 'application/pdf',
'uploadType' => 'multipart',
'fields' => 'id'));
printf("File ID: %s\n", $file->id); // Your file id
}
public function viewGoogleDriveFile(){
$fileId = $_GET['fileId'];
$client = new Google_Client();
$client->setAuthConfig(public_path('service_account.json'));
$client->setScopes(array('https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.file'));
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
$service = new Google_Service_Drive($client);
$response = $service->files->get($fileId, array(
'alt' => 'media' ));
header('Content-type:application/pdf');
echo $content = $response->getBody()->getContents();
}
Maybe you can check this SO Post. It points out how to login and file upload on google drive.
Here is the code from github specified in the post.
<?php
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
include_once __DIR__ . '/../vendor/autoload.php';
include_once "templates/base.php";
echo pageHeader("File Upload - Uploading a large file");
/*************************************************
* Ensure you've downloaded your oauth credentials
************************************************/
if (!$oauth_credentials = getOAuthCredentialsFile()) {
echo missingOAuth2CredentialsWarning();
return;
}
/************************************************
* The redirect URI is to the current page, e.g:
* http://localhost:8080/large-file-upload.php
************************************************/
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$client = new Google_Client();
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/drive");
$service = new Google_Service_Drive($client);
// add "?logout" to the URL to remove a token from the session
if (isset($_REQUEST['logout'])) {
unset($_SESSION['upload_token']);
}
/************************************************
* If we have a code back from the OAuth 2.0 flow,
* we need to exchange that with the
* Google_Client::fetchAccessTokenWithAuthCode()
* function. We store the resultant access token
* bundle in the session, and redirect to ourself.
************************************************/
if (isset($_GET['code'])) {
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
$client->setAccessToken($token);
// store in the session also
$_SESSION['upload_token'] = $token;
// redirect back to the example
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
// set the access token as part of the client
if (!empty($_SESSION['upload_token'])) {
$client->setAccessToken($_SESSION['upload_token']);
if ($client->isAccessTokenExpired()) {
unset($_SESSION['upload_token']);
}
} else {
$authUrl = $client->createAuthUrl();
}
/************************************************
* If we're signed in then lets try to upload our
* file.
************************************************/
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $client->getAccessToken()) {
/************************************************
* We'll setup an empty 20MB file to upload.
************************************************/
DEFINE("TESTFILE", 'testfile.txt');
if (!file_exists(TESTFILE)) {
$fh = fopen(TESTFILE, 'w');
fseek($fh, 1024*1024*20);
fwrite($fh, "!", 1);
fclose($fh);
}
$file = new Google_Service_Drive_DriveFile();
$file->name = "Big File";
$chunkSizeBytes = 1 * 1024 * 1024;
// Call the API with the media upload, defer so it doesn't immediately return.
$client->setDefer(true);
$request = $service->files->create($file);
// Create a media file upload to represent our upload process.
$media = new Google_Http_MediaFileUpload(
$client,
$request,
'text/plain',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize(TESTFILE));
// Upload the various chunks. $status will be false until the process is
// complete.
$status = false;
$handle = fopen(TESTFILE, "rb");
while (!$status && !feof($handle)) {
// read until you get $chunkSizeBytes from TESTFILE
// fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
// An example of a read buffered file is when reading from a URL
$chunk = readVideoChunk($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
// The final value of $status will be the data from the API for the object
// that has been uploaded.
$result = false;
if ($status != false) {
$result = $status;
}
fclose($handle);
}
function readVideoChunk ($handle, $chunkSize)
{
$byteCount = 0;
$giantChunk = "";
while (!feof($handle)) {
// fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
$chunk = fread($handle, 8192);
$byteCount += strlen($chunk);
$giantChunk .= $chunk;
if ($byteCount >= $chunkSize)
{
return $giantChunk;
}
}
return $giantChunk;
}
?>
<div class="box">
<?php if (isset($authUrl)): ?>
<div class="request">
<a class='login' href='<?= $authUrl ?>'>Connect Me!</a>
</div>
<?php elseif($_SERVER['REQUEST_METHOD'] == 'POST'): ?>
<div class="shortened">
<p>Your call was successful! Check your drive for this file:</p>
<p><?= $result->name ?></p>
<p>Now try downloading a large file from Drive.
</div>
<?php else: ?>
<form method="POST">
<input type="submit" value="Click here to upload a large (20MB) test file" />
</form>
<?php endif ?>
</div>
<?= pageFooter(__FILE__) ?>
And for additional reference open this So post.
You may check this post from github relating to login error and to retrieve the access token this documentation defined the steps needed.
The user has a login required issue when trying to insert a file in Google Drive.
This is the response.
You'll need to grant your app access to your user account using an
OAuth2 authorization flow. Once you've done this, the application will
be granted an access token and refresh token, and will be able to
maintain access to your account using these.
In which you will need these general process:
When you create your application, you register it using the Google API Console. Google then provides information you'll need later, such as a client ID and a client secret.
Activate the Drive API in the Google API Console. (If the API isn't listed in the API Console, then skip this step.)
When your application needs access to user data, it asks Google for a particular scope of access.
Google displays a consent screen to the user, asking them to authorize your application to request some of their data.
If the user approves, then Google gives your application a short-lived access token.
Your application requests user data, attaching the access token to the request.
If Google determines that your request and the token are valid, it returns the requested data.
I am using the php code sample for uploading a video provided by youtube, which can be found here: https://developers.google.com/youtube/v3/code_samples/php#upload_a_video
However, when the session starts, it requires the user to authorise it, so it takes you to the authorise page, then redirects you back. On doing this, it uploads twice, I assume it is trying to upload the video it could not do when it was not authorised. It only double uploads when authorising, and not when the page is reloaded and the session is still valid.
How do I stop this initial duplicate upload?
You can use the following code to upload the file just after user has signin when user click a submit button with the path defined in a text input :
<?php
/**
* Library Requirements
*
* 1. Install composer (https://getcomposer.org)
* 2. On the command line, change to this directory (api-samples/php)
* 3. Require the google/apiclient library
* $ composer require google/apiclient:~2.0
*/
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}
require_once __DIR__ . '/vendor/autoload.php';
session_start();
$response = "";
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = 'YOUR_CLIENTID';
$OAUTH2_CLIENT_SECRET = 'YOUR_CLIENT_SECRET';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
$videoPath = "";
if (isset($_GET['videoPath'])){
$videoPath = $_GET['videoPath'];
}
else if(isset($_SESSION['videoPath'])){
$videoPath = $_SESSION['videoPath'];
}
if(isset($videoPath) && !isset($_GET['state']) && file_exists($videoPath)) {
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("tag1", "tag2"));
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "private";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$response .= "<h3>Video Uploaded</h3><ul>";
$response .= sprintf('<li>%s (%s)</li>',
$status['snippet']['title'],
$status['id']);
$response .= '</ul>';
$_SESSION['path'] = "";
}
else{
$response = "no path was specified or file doesn't exist";
file_put_contents('php://stderr', print_r("no path was specified or file doesn't exist", TRUE));
}
} catch (Google_Service_Exception $e) {
$response = htmlspecialchars($e->getMessage());
} catch (Google_Exception $e) {
$response = htmlspecialchars($e->getMessage());
}
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
} else {
if(isset($_GET['videoPath'])){
$_SESSION["videoPath"] = $_GET['videoPath'];
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
header('Location: ' . $authUrl);
}
}
?>
<!doctype html>
<html>
<head>
<title>Upload Video</title>
</head>
<body>
<div>
<form id="form" action="resumable_upload.php"">
<label>Enter the path to the video to upload
:
<input id="video-path" name="videoPath" value='/path/to/video' type="text" />
</label>
<input name="action" type="submit" value="Upload video" />
</form>
<div id="playlist-container">
<?php echo $response ?>
</div>
</div>
</body>
</html>
But if the page gets refreshed or if the user clicks the button by mistake one more time, it will re-upload the video. Check this post to deal with the duplicated video issue
I know this question is old but this is a issue I was struggling with for a while.
In my situation, I had a form that needed to pass values to my upload script, and if a user wasn't signed in then the post values would get lost during the sign in process. So I came up with a way using session variables.
First towards the start of my script I set a variable to count the 'page' views -
// set the session views
if (!isset($_SESSION['views'])) {
$_SESSION['views'] = 0;
}
// every view increments
$_SESSION['views'] = $_SESSION['views'] + 1;
Then I stored session variables.
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authorID = $_POST['a_id'];
$videoTitle = $_POST['ytu_title'];
// Set session variables
$vidID = $_POST['vid_id'];
$_SESSION["author"] = $_POST['a_id'];
$_SESSION["title"] = $_POST['ytu_title'];
$_SESSION["video"] = $vidID;
Then I put an if statement to check the views before uploading -
// if its on the third view or more
if ($_SESSION['views'] >= 3) {
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle($_SESSION["title"]);
$snippet->setDescription("Youtube Video.");
$snippet->setTags(array(
"test",
"test 2"
));
// and rest of the upload part from upload php script
// etc etc
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload($client, $insertRequest, 'video/*', null, true, $chunkSizeBytes);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
} // closing if statement
I was finally able to fix my issue with the if statement before uploading.
I'm trying to search a user's gmail account for emails with attachments and collect statistics. I can successfully use oauth to authenticate and then use the gmail api to get the message ids ($id). Then I need to get headers, and finally, I need to get the messages themselves.
That has proven difficult. (And I eventually need to do this for all messages from all folders.)
I have occasionally gotten the headers using the gmail api, but everything bogged down and the code below crashes my server (WTF?).
I am considering using Zend to get the headers and attachments because it supports oauth, but the getmessage($id) function of Zend does not use the id that the api gives needs and I haven't found how to convert them.
Any help would be immensely appreciated.
<?php
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
include_once "templates/base.php";
session_start();
set_include_path("../src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Gmail.php';
/************************************************
ATTENTION: Fill in these values! Make sure
the redirect URI is to this page, e.g:
http://localhost:8080/user-example.php
************************************************/
$client_id = 'XXXXXXXXXXX.apps.googleusercontent.com'; // Client ID
$client_secret = 'YYYYYYYYYYYYY'; // Client Secret
$redirect_uri = 'https://www.example.com/Google/testgmail.php'; // Redirect URI
/************************************************
Make an API request on behalf of a user. In
this case we need to have a valid OAuth 2.0
token for the user, so we need to send them
through a login flow. To do this we need some
information from our API console project.
************************************************/
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/gmail.readonly");
$gm_service = new Google_Service_Gmail($client);
/************************************************
Boilerplate auth management - see
user-example.php for details.
************************************************/
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
}
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
} else {
$authUrl = $client->createAuthUrl();
}
/************************************************
If we're signed in, retrieve channels from YouTube
and a list of files from Drive.
************************************************/
if ($client->getAccessToken()) {
$_SESSION['access_token'] = $client->getAccessToken();
}
echo pageHeader("User Query - Multiple APIs");
function listMessages($service, $userId) {
$pageToken = NULL;
$messages = array();
$opt_param = array();
do {
try {
if ($pageToken) {
$opt_param['pageToken'] = $pageToken;
$opt_param['q'] = 'filename:(jpg OR png OR gif)';
$opt_param['maxResults'] = 100;
}
$messagesResponse = $service->users_messages->listUsersMessages($userId, $opt_param);
if ($messagesResponse->getMessages()) {
$messages = array_merge($messages, $messagesResponse->getMessages());
$pageToken = $messagesResponse->getNextPageToken();
}
} catch (Exception $e) {
print 'An error occurred: ' . $e->getMessage();
}
} while ($pageToken);
$optParamsGet = array();
$optParamsGet['format'] = 'metadata';
foreach ($messages as $message) {
$message_id = $message->getId();
print 'Message with ID: ' . $message_id . '<br/>';
// This is the section that causes it to crash !!!
// $message2 = $service->users_messages->get($userId,$message_id,$optParamsGet); //if this line is uncommented, then everything stops working.
// if ($message2->getPayload()) {
// $messagePayload = $message2->getPayload();
// $headers = $message2->getPayload()->getHeaders();
// var_dump($headers);
// }
// This is the section that causes it to crash !!!
}
return $messages;
}
?>
<div class="box">
<div class="request">
<?php if (isset($authUrl)) { ?>
<a class='login' href='<?php echo $authUrl; ?>'>Connect Me!</a>
<?php } else {
echo "<h3>Results Of Gmail search:</h3>";
$messagelist = listMessages($gm_service, 'me');
} ?>
</div>
</div>
$id is the index of the message inside of the inbox. So the most recent email received has the index 0
You can find an implementation of the algorith for search email with attachments in this repo
https://bitbucket.org/startupbootstrap/email-attachments/src/ae4739bf956c8958a4128a34eb04c8fd855c0500/EmailAttachments.php?at=master#cl-85