So this is supposed to be a quick article detailing how I used a PHP function to upload a video file to Google Drive. Note that this example does not involve installing the Google Client Library for PHP. So no classes or built-in functions that you didn't write or know what they're doing.
Why?
The objective here is to upload a video file to my Google Drive. This assumes you have already "Enabled the Drive API" via your Google Developers console as well as gotten your OAuth 2.0 access/refresh tokens and specified the appropriate scopes.
The scopes I chose were to do with getting a working example rather than the recommended scope, though you may only need the first (untested):
https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile
How?
I've listed below 3 methods, the first follows the manual (or the logic thereof as I don't use the client library) and is a function sending two requests, the second is the appropriate multipart function which uploads and names the file in a single request, and the third is a 'nice-to-have' upload to the specified folder.
Method #1: two requests
1. Send the media file
2. Update the name of the file you just uploaded
$GAPIS = 'https://www.googleapis.com/';
function uploadFile($access_token, $file, $mime_type, $name) {
global $GAPIS;
$ch1 = curl_init();
// don't do ssl checks
curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
// do other curl stuff
curl_setopt($ch1, CURLOPT_URL, $GAPIS . 'upload/drive/v3/files?uploadType=media');
curl_setopt($ch1, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS, file_get_contents($file));
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
// set authorization header
curl_setopt($ch1, CURLOPT_HTTPHEADER, array('Content-Type: '.$mime_type, 'Content-Length: ' . filesize($file), 'Authorization: Bearer ' . $access_token) );
// execute cURL request
$response=curl_exec($ch1);
if($response === false){
$output = 'ERROR: '.curl_error($ch1);
} else{
$output = $response;
}
// close first request handler
curl_close($ch1);
// now let's get the ID of the file we just created
// and submit the file metadata
$this_response_arr = json_decode($response, true);
if(isset($this_response_arr['id'])){
$this_file_id = $this_response_arr['id'];
$ch2 = curl_init();
// don't do ssl checks
curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch2, CURLOPT_SSL_VERIFYHOST, false);
// do other curl stuff
curl_setopt($ch2, CURLOPT_URL, $GAPIS . 'drive/v3/files/'.$this_file_id);
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, 'PATCH');
// initialize fields to submit
$post_fields = array();
// remove extension
$this_file_name = explode('.', $name);
// submit name field
$post_fields['name']=$this_file_name[0];
curl_setopt($ch2, CURLOPT_POSTFIELDS, json_encode($post_fields));
// return response as a string
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
// set authorization header
curl_setopt($ch2, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer ' . $access_token) );
// execute cURL request
$response=curl_exec($ch2);
if($response === false){
$output = 'ERROR: '.curl_error($ch2);
} else{
$output = $response;
}
// close second request handler
curl_close($ch2);
}
return $output;
}
Usage:
$mime_type = 'video/mp4'; // could be 'image/jpeg', etc. $new_name = 'My Video'; $the_file_and_path = '../videos/my_video.mp4'; $result = uploadFile($my_access_token, $the_file_and_path, $mime_type, $new_name);This method was the first one I could get working but it's a bit excessive having to send two requests (albeit in one function) especially with imposed limit requests. I can halve this so let's upgrade!
Method #2: Mulitipart single request
This is my recommended version. In this function, we are sending the metadata before the media:
$GAPIS = 'https://www.googleapis.com/';
function uploadFile($access_token, $file, $mime_type, $name) {
global $GAPIS;
$ch1 = curl_init();
// don't do ssl checks
curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
$my_beautiful_body = '
--joes_awesome_divider
Content-Type: application/json; charset=UTF-8
{
"name": "'.$name.'"
}
--joes_awesome_divider
Content-Type: '.$mime_type.'
'.file_get_contents($file).'
--joes_awesome_divider--
';
// do other curl stuff
curl_setopt($ch1, CURLOPT_URL, $GAPIS . 'upload/drive/v3/files?uploadType=multipart');
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $my_beautiful_body);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
// set authorization header
curl_setopt($ch1, CURLOPT_HTTPHEADER, array('Content-Type: multipart/related; boundary=joes_awesome_divider', 'Authorization: Bearer ' . $access_token) );
// execute cURL request
$response=curl_exec($ch1);
if($response === false){
$output = 'ERROR: '.curl_error($ch1);
} else{
$output = $response;
}
// close first request handler
curl_close($ch1);
return $output;
}
Usage:
$mime_type = 'video/mp4'; // could be 'image/jpeg', etc. $new_name = 'My Video'; $the_file_and_path = '../videos/my_video.mp4'; $result = uploadFile($my_access_token, $the_file_and_path, $mime_type, $new_name);
Method #3: As method 2 but with specified folder
To get the folder ID, simply browse to the Google Drive folder in your browser and note the last string in the URL. So in https://drive.google.com/drive/folders/<SomeAlphaNumericCharactersAndThenSome>, the value where "<SomeAlphaNumericCharactersAndThenSome>" sits will be your folder ID.
$GAPIS = 'https://www.googleapis.com/';
function uploadFile($access_token, $file, $mime_type, $name, $folder) {
global $GAPIS;
$ch1 = curl_init();
// don't do ssl checks
curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
$my_beautiful_body = '
--joes_awesome_divider
Content-Type: application/json; charset=UTF-8
{
"name": "'.$name.'",
"parents": ["'.$folder.'"]
}
--joes_awesome_divider
Content-Type: '.$mime_type.'
'.file_get_contents($file).'
--joes_awesome_divider--
';
// do other curl stuff
curl_setopt($ch1, CURLOPT_URL, $GAPIS . 'upload/drive/v3/files?uploadType=multipart');
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $my_beautiful_body);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
// set authorization header
curl_setopt($ch1, CURLOPT_HTTPHEADER, array('Content-Type: multipart/related; boundary=joes_awesome_divider', 'Authorization: Bearer ' . $access_token) );
// execute cURL request
$response=curl_exec($ch1);
if($response === false){
$output = 'ERROR: '.curl_error($ch1);
} else{
$output = $response;
}
// close first request handler
curl_close($ch1);
return $output;
}
Usage:
$mime_type = 'video/mp4'; $new_name = 'My Video'; $the_file_and_path = '../videos/my_video.mp4'; $folder_id = 'l4S9F71BMqlXWtl4uGvy2etd_hrNwmroi'; $result = uploadFile($my_access_token, $the_file_and_path, $mime_type, $new_name, $folder_id);
Response(s)
The response should be a JSON with the file metadata (yours will be different but this is just an example). You may want to extract the ID so that you can manage the file further.
{
"kind": "drive#file",
"id": "1srXLU-lotsofalphanumericcharacters_",
"name": "my_video.mp4",
"mimeType": "video/mp4"
}
Additional:
Why not? Let's add a description and some security where we disable download, sharing, etc. to the viewers (except the owner). In other words, ticking the owner settings under the advanced sharing settings programmatically:
- Prevent editors from changing access and adding new people :: Set by "writersCanShare" = false
- Disable options to download, print and copy for commenters and viewers :: Set by "copyRequiresWriterPermission" = true

To do this, set the metadata to the following in the above function:
{
"name": "'.$name.'",
"parents": ["'.$folder.'"],
"description": "'.$desc.'",
"copyRequiresWriterPermission": true,
"writersCanShare": false
}
Reminder: if you are adding the description, then pass this as a parameter to the above function.Source(s):
Discussion
Comments
Questions, corrections and useful additions are reviewed before appearing here.
No comments yet. Start the discussion.