26

I want to create a file with content using Google Drive API v3. I have authenticated via OAuth and have the Drive API loaded. Statements like the following work (but produce a file without content):

gapi.client.drive.files.create({
    "name": "settings",
}).execute();

Unfortunately I cannot figure out how to create a file that has a content. I cannot find a JavaScript example using Drive API v3. Are there some special parameters that I need to pass?

For simplicity, assume that I have a String like '{"name":"test"}' that is in JSON format that should be the content of the created file.

Geminus
  • 655
  • 1
  • 6
  • 10
  • Check this documentation, I know is for v2 but the process is very similar. You would need to change the version in the url to v3 and the parameter according to the v3 ( eg. instead of 'title' use 'name') https://developers.google.com/drive/v2/reference/files/insert#examples – Gerardo Jan 20 '16 at 18:22
  • Thanks for the link, but from I think this is somewhat against the spirit of using the library (at least in v3): In no other case do I have to build the request myself. Here I have to choose thinks like I want it to be a 'POST' request and have to concatenate things into a long string delimited by a boundary. I think the point of v3 was to avoid these things and I guess there should be another way to do it. – Geminus Jan 20 '16 at 20:43
  • Take a look at [upload.js](https://github.com/googledrive/cors-upload-sample) from some devs at Google. I have a modified version for drive v3 api [here](https://gist.github.com/DrPaulBrewer/eaea4ad927389643e56ce566d4ed513e) – Paul Jan 17 '18 at 04:55

5 Answers5

27

Unfortunately, I have not found an answer using only the google drive api, instead I followed Gerardo's comment and used the google request api. Below is a function that uploads a file to google drive.

var createFileWithJSONContent = function(name,data,callback) {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  const contentType = 'application/json';

  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\r\n' +
        data +
        close_delim;

    var request = gapi.client.request({
        'path': '/upload/drive/v3/files',
        'method': 'POST',
        'params': {'uploadType': 'multipart'},
        'headers': {
          'Content-Type': 'multipart/related; boundary="' + boundary + '"'
        },
        'body': multipartRequestBody});
    if (!callback) {
      callback = function(file) {
        console.log(file)
      };
    }
    request.execute(callback);
}
Geminus
  • 655
  • 1
  • 6
  • 10
12

here is the solution with gapi.client.drive,

var parentId = '';//some parentId of a folder under which to create the new folder
var fileMetadata = {
  'name' : 'New Folder',
  'mimeType' : 'application/vnd.google-apps.folder',
  'parents': [parentId]
};
gapi.client.drive.files.create({
  resource: fileMetadata,
}).then(function(response) {
  switch(response.status){
    case 200:
      var file = response.result;
      console.log('Created Folder Id: ', file.id);
      break;
    default:
      console.log('Error creating the folder, '+response);
      break;
    }
});

you'll need to connect/authorise with either of the following scopes

https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.file

EDIT: it is possible to create google files (doc, sheets and so on) by changing the mimeType from application/vnd.google-apps.folder to one of the supported google mime types. HOWEVER, as of now it not possible to upload any content into created files.

To upload files, use the solution provided by @Geminus. Note you can upload a text file or a csv file and set its content type to google doc or google sheets respectively, and google will attempt to convert it. I have tested this for text -> doc and it works.

Uri
  • 25,622
  • 10
  • 45
  • 72
Aurovrata
  • 2,000
  • 27
  • 45
  • 2
    This creates a folder, not a file, though. – David Given Jun 13 '17 at 16:42
  • this creates a folder actually, I will post shortly the solution for a file – Aurovrata Jun 13 '17 at 16:46
  • @DavidGiven, I just edited my answer, you can create a doc/sheet or any other supported file type, but you cannot use `gapi.client.drive.files.create` to actually upload content. – Aurovrata Jun 13 '17 at 18:25
  • I did not edit your answer. I edited my comment above (because I misread your code and the comment was wrong). – David Given Jun 13 '17 at 18:26
  • Ah, yeah! English is a stupid language, isn't it? Anyway, I appreciate the help; I'd still like an actual solution here... – David Given Jun 13 '17 at 18:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/146566/discussion-between-aurovrata-and-david-given). – Aurovrata Jun 13 '17 at 18:40
  • After a long long search this is the only piece of code which works! Thanks mate. :) – Tulon Aug 18 '20 at 02:59
11

Using gapi.client.drive, it is not possible to upload file content. You can only upload metadata.

Instead it is recommended to work directly with the Google REST API. This solution uses a FormData object to build the multipart form body, which simplifies the implementation, and gapi.auth.getToken() to retrieve the required access token. The solution also works with Google shared drives:

var fileContent = "sample text"; // fileContent can be text, or an Uint8Array, etc.
var file = new Blob([fileContent], {type: "text/plain"});
var metadata = {
    "name": "yourFilename",
    "mimeType": "text/plain",
    "parents": ["folder id or 'root'"], // Google Drive folder id
};

var accessToken = gapi.auth.getToken().access_token;
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));
form.append('file', file);

fetch("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&supportsAllDrives=true", {
    method: 'POST',
    headers: new Headers({ 'Authorization': 'Bearer ' + accessToken }),
    body: form,
}).then((res) => {
    return res.json();
}).then(function(val) {
    console.log(val);
});
Mario Varchmin
  • 3,704
  • 4
  • 18
  • 33
  • I am a bit late to the party, but do you have a source for the part where it's not possible to upload file content with gapi? I am looking at the documentation and am confused? @mario-varchmin – bouffelec Mar 13 '22 at 18:45
  • @bouffelec I keep only working code, not code, that is not working. I am not saying that an upload is not possible with gapi, in fact my proposed solution is using gapi. What I meant is that this was not possible (at the time of writing) using the Google API Client Library for JavaScript, which Geminus was having problems with. – Mario Varchmin Mar 13 '22 at 20:37
-1

this works fine usin v3:

        var fileMetadata = {
            'name' : 'MaxBarrass',
            'mimeType' : 'application/vnd.google-apps.folder'
        };

        gapi.client.drive.files.create({
            resource: fileMetadata,
            fields: 'id'
        }).execute(function(resp, raw_resp) {
            console.log('Folder Id: ', resp.id);
        });
Max Barrass
  • 2,776
  • 1
  • 19
  • 10
  • 3
    this appears to be for creating a folder, not a file. – ADyson May 22 '17 at 12:12
  • yeah you can make folder with it as... it does say "files.create" in "gapi.client.drive.files.create", its all nodes in the end so and they are more like files than folders... – Max Barrass Aug 22 '17 at 01:12
  • 2
    I realise that, but the question specifically asked about creating files. So it's hard to see why an example showing the creation of a folder would be useful. – ADyson Aug 22 '17 at 08:37
-1
/*  Now to create a new file */ 
function insertNewFile(folderId) 
{   
    var content = " ";  
    var FolderId = ""; 
    var contentArray = new Array(content.length);
    for (var i = 0; i < contentArray.length; i++) 
    {
        contentArray[i] = content.charCodeAt(i);
    }
    var byteArray = new Uint8Array(contentArray);
    var blob = new Blob([byteArray], {type: 'text/plain'});     
    insertFile(blob, fileInserted, folderId); 
} 
function fileInserted(d) 
{   
    setPercent("100");   
    var FI = FolderId;  
    if(FI !== myRootFolderId)
    {           
        insertFileIntoFolder(FI, d.id);         
        removeFileFromFolder(d.parents[0].id,d.id);     
    }   
    openFile(d.id); 
} 
function insertFileIntoFolder(folderId, fileId) 
{   
    var body = {'id': folderId};   
    var request = gapi.client.drive.parents.insert({
        'fileId': fileId,
        'resource': body   });   
    request.execute(function(resp) { }); 
 } 

Source: https://gist.github.com/mkaminsky11/8624150

Anagha
  • 740
  • 1
  • 10
  • 16
  • 2
    You missed out `insertFile()`, which is actually doing the work; it's the same as @Geminus' answer above, using an explicit post to upload the data. – David Given Jun 13 '17 at 16:45