Need help regarding inserting a file to google drive through api. The api documentation for this purpose does not clearly explains how to send the actual body of the file through http post request.
-
What language are you working in? Can you add a link to the relevant API documentation? – jsbueno Apr 25 '12 at 14:24
-
1Thanks for answering. The link I am referring is https://developers.google.com/drive/v1/reference/files/insert. – Niranja Apr 25 '12 at 14:31
-
What language are you using? We have examples there for a few. – Ali Afshar Apr 25 '12 at 15:14
-
The page you are referring to there contains examples in many programming languages that explains how to upload the body of a file. Are you looking for an example with the protocol? – Nicolas Garnier Apr 25 '12 at 19:11
5 Answers
The documentation on insert operations already contains examples in a bunch of programming languages, here is how to do it using the HTTP based protocol of the Google Drive API.
First, POST the new file metadata to the Drive endpoint. It has to be in the form of a File resource JSON object:
POST /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <OAuth 2.0 access token here>
...
{
"title": "file_name.extension",
"mimeType": "mime/type",
"description": "Stuff about the file"
}
The response body will be a JSON representation of the newly created File resource. It will look like:
{
"kind": "drive#file",
"id": string,
"etag": etag,
"selfLink": string,
"title": "file_name",
"mimeType": "mime/type",
"description": "Stuff about the file"
...
"downloadUrl": string,
...
}
This is a confirmation that the file entry has been created. Now you need to upload the content. To do that you need to take the ID of the file given by the id JSON attribute in the response above and PUT the content of the actual file to the upload endpoint with an OAuth 2.0 authorized request. It should look like:
PUT /upload/drive/v2/files/{id}?uploadType=media HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <OAuth 2.0 access token here>
Content-Type: mime/type
<file content here>
You are done :)
There is also a way to do this in 1 single POST request using a multipart request where you post the metadata of the file at the same time as the content. Here is an example:
POST /upload/drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <OAuth 2.0 access token here>
Content-Type: multipart/form-data; boundary=287032381131322
...
--287032381131322
Content-Type: application/json
{
"title": "file_name.extension",
"mimeType": "mime/type",
"description": "Stuff about the file"
}
--287032381131322
Content-Type: mime/type
<file content here>
--287032381131322--
The response will contain the metadata of the newly created file. You may also use the Content-Transfer-Encoding: base64 header in the sub-part of the request to be able to pass the data of the file as Base 64 encoded.
Lastly there is also a resumable upload protocol which is convenient to upload large files, offer a pause/resume feature and/or upload files with flaky internet connection.
PS: most of this is now described in Drive's file upload documentation.

- 12,134
- 2
- 42
- 39
-
Thanks Nicolas. Your solution helped me understand the situation. Actually the second part of sending the file content to download url was not mentioned. But now I am facing a new problem, that's when i tried posting the file metadata i received an error saying "The authenticated user has not installed the app with client id ". Can you please help me with this? – Niranja Apr 26 '12 at 07:06
-
Niranja > In the Google Drive world Google Drive applications only have access to the user's Drive if the user has installed the app (going through the OAuth 2 flow is not enough). To develop you will have to create a Drive enabled Chrome Web Store listing (see https://developers.google.com/drive/listing) and install it. – Nicolas Garnier Apr 26 '12 at 07:34
-
Oh I missed it. Thanks again. Actually i thought it's similar to the procedure we follow while creating a Facebook App and didn't read more about it in documentation. – Niranja Apr 26 '12 at 07:50
-
Hi Nicolas. Can you please tell me that is it necessary to pay the registration fees for testing our app? – Niranja Apr 26 '12 at 14:15
-
For testing you don't have to publish your application publicly, you should publish it to a trusted tester group (there is a button on the bottom for that). Can you try it? – Nicolas Garnier Apr 26 '12 at 15:07
-
Yes i tried using that button and it's asking me to pay developer registration fee. Anyways I think I will have to pay for testing the app, so will proceed soon after paying and purchasing a domain for the app. – Niranja Apr 27 '12 at 09:55
-
Hi Nicolas I have paid for publishing to test accounts now from where can my app testers install that app. – Niranja Apr 27 '12 at 11:12
-
I have installed the app as you instructed but still facing the same error saying "The authenticated user has not installed the app with client id " while inserting the file through api. – Niranja Apr 28 '12 at 06:29
-
Miranja > Make sure that the App IDs match - in your Chrome Web Store app's JSON file and in your actual code. Have you installed the app by Clicking the "Add to Chrome" – Nicolas Garnier Apr 28 '12 at 11:51
-
I have entered the app id that I see in the drive sdk section at the google api console and yeah I have also installed the app from chrome store. I hope I am supposed to enter the app id and not the client id. – Niranja Apr 28 '12 at 12:00
-
I have posted a new question related to this problem - http://stackoverflow.com/questions/10361278/i-am-facing-the-authenticated-user-has-not-installed-the-app-with-client-id-er – Niranja Apr 28 '12 at 12:04
Thanks for the explanation! This has taken my hours of going around in circles with the crappy google SDK documentation (sorry I had to get my rant out).
Here's a function I made that will update a text file (as you can see I'm updating html):
function gd_updateFile(fileId, folderId, text, callback) {
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var contentType = "text/html";
var metadata = {'mimeType': contentType,};
var multipartRequestBody =
delimiter + 'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter + 'Content-Type: ' + contentType + '\r\n' + '\r\n' +
text +
close_delim;
if (!callback) { callback = function(file) { console.log("Update Complete ",file) }; }
gapi.client.request({
'path': '/upload/drive/v2/files/'+folderId+"?fileId="+fileId+"&uploadType=multipart",
'method': 'PUT',
'params': {'fileId': fileId, 'uploadType': 'multipart'},
'headers': {'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'},
'body': multipartRequestBody,
callback:callback,
});
}
It's a mashup of the google example (which uses a binary file from upload), and the nice explanation from @Nivco above.

- 337
- 2
- 6
4 years later, this is still difficult to figure out. I took @user1158023's answer to support uploading of images. I am using API v3 and superagent.js to help me out (since gapi.client.request is sending the request to content.googleapis.com!?). Hopefully someone may find this useful.
function gd_uploadFile(name, contentType, data, callback) {
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
contentType = contentType || "text/html";
var metadata = {
name: name,
'mimeType': contentType
};
var multipartRequestBody =
delimiter + 'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n';
//Transfer images as base64 string.
if (contentType.indexOf('image/') === 0) {
var pos = data.indexOf('base64,');
multipartRequestBody += 'Content-Transfer-Encoding: base64\r\n' + '\r\n' +
data.slice(pos < 0 ? 0 : (pos + 'base64,'.length));
} else {
multipartRequestBody += + '\r\n' + data;
}
multipartRequestBody += close_delim;
if (!callback) { callback = function(file) { console.log("Update Complete ", file) }; }
superagent.post('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart').
set('Content-Type', 'multipart/form-data; boundary="' + boundary + '"').
set('Authorization', 'Bearer ' + gapi.auth.getToken().access_token).
send(multipartRequestBody).
end(function () {
console.log(arguments);
});
}
//On upload
$('#file')[0].onchange = function () {
var file = $('#file')[0].files[0];
if (file && file.type === 'image/jpeg') {
var reader = new FileReader();
reader.onloadend = function () {
var data = reader.result;
gd_uploadFile('img.jpg', 'image/jpeg', data, function () {
console.log(arguments);
});
}
reader.readAsDataURL(file);
}
};
index.html
...
<form>
<span>Upload: </span><input id="file" type="file" name="myFile">
</form>
...

- 1,712
- 19
- 14
-
This saved me! Thank you sir very much!! Is it possible to specifiy a folder that it should be uploaded into in the metadata? – Noitidart Feb 23 '16 at 11:39
-
Oh I spoke to soon, I simply had to add to the `metadata` object `parents: ['0B5IwavgVGMN9ekR2dEhuaUxkZTA']` where that string is the id of the folder I wanted to upload it into. Thanks again @Munawwar ! – Noitidart Feb 23 '16 at 11:49
-
I have same code but i have not used input type="file" i have used url and how to upload using url to upload file in google drive ? – Apr 14 '16 at 14:41
I whish there were better examples for drive gapis v3... It took me some time to figure out how to upload new content into an existing file created with
gapi.client.drive.files.create({ "name" : "savefile.txt" }).execute(function(file) { console.log("Created file " + file.name + " id: " + file.id); });
but eventually I tried the "lucky" combination of adding the fileId to the path and changing the method to PATCH
function uploadFile(id, text)
{
var auth_token = gapi.auth.getToken().access_token;
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var metadata = {
description : 'savefile for my game',
'mimeType': 'application/json'
};
var multipartRequestBody =
delimiter + 'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter + 'Content-Type: application/json\r\n\r\n' +
text +
close_delim;
gapi.client.request
( {
'path': '/upload/drive/v3/files/'+id,
'method': 'PATCH',
'params': {'fileId': id, 'uploadType': 'multipart'},
'headers': { 'Content-Type': 'multipart/form-data; boundary="' + boundary + '"', 'Authorization': 'Bearer ' + auth_token, },
'body': multipartRequestBody
}).execute(function(file) { console.log("Wrote to file " + file.name + " id: " + file.id); });
}
But I guess that now the whole documentation at https://developers.google.com/drive/v3/reference/files/update starts to make sense to me :-)

- 181
- 3
-
Just a quick note that the auth_token in the above example is not necessary if you are using gapi.client.init and specifying your token etc. – smaudet Sep 22 '17 at 11:16
The Google Drive API team released v3 at the end of 2015, and in that release, insert()
changed names to create()
so as to better reflect the file operation. The documentation has also been improved: there's now a special guide devoted to uploads (simple, multipart, and resumable) that comes with sample code in Java, Python, PHP, C#/.NET, Ruby, JavaScript/Node.js, and iOS/Obj-C for uploading a regular file and another one for importing a CSV file as a Google Sheet.
Just to show up straightforward it is, below is one alternate Python solution (to the sample in the docs) for short files ("simple upload") where you don't need the apiclient.http.MediaFileUpload
class. This snippet assumes your auth code works where your service endpoint is DRIVE
with a minimum auth scope of https://www.googleapis.com/auth/drive.file
.
# filenames & MIMEtypes
DST_FILENAME = 'inventory'
SRC_FILENAME = DST_FILENAME + '.csv'
SHT_MIMETYPE = 'application/vnd.google-apps.spreadsheet'
CSV_MIMETYPE = 'text/csv'
# Import CSV file to Google Drive as a Google Sheets file
METADATA = {'name': DST_FILENAME, 'mimeType': SHT_MIMETYPE}
rsp = DRIVE.files().create(body=METADATA, media_body=SRC_FILENAME).execute()
if rsp:
print('Imported %r to %r (as %s)' % (SRC_FILENAME, DST_FILENAME, rsp['mimeType']))
Note that if you're writing an Android app, there's a separate Google Drive API for Android with its own set of docs. Finally, if you're using JavaScript on Google Apps Script, both the Drive Service native object and Drive Advanced Service are still using v2 of the API.

- 10,689
- 3
- 54
- 53