25
votes

How can I upload a local CSV file to Google Drive using the Drive API v2 so that the uploaded file is in the native Google Spreadsheet format. Preferably in Python, but a raw HTTP request will suffice.

What I tried:

  1. request body content-type: 'application/vnd.google-apps.spreadsheet', media_body content-type: 'text/csv'. --> 401 Bad Request

  2. request body content-type: 'application/vnd.google-apps.spreadsheet', media_body content-type: 'application/vnd.google-apps.spreadsheet'. --> 400 Bad Request

  3. ... (a couple of others such as leaving a property out and similar, usually got 400 or Drive didn't recognise it as a native spreadsheet)

5

5 Answers

24
votes

Your insert request should specify text/csv as the content-type. The trick to get the file converted is to add the ?convert=true query parameter to the request url:

https://developers.google.com/drive/v2/reference/files/insert

10
votes

(Mar 2017) Note, while the question specifically asks about Drive API v2, developers should know that 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. There's also no more convert flag -- you just specify MIMEtypes... imagine that!

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 to upload a file and another that imports 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']))
7
votes

Claudio Cherubino's answer is correct -- you have to add the parameter manually. Since you asked in Python though, here's a concrete example:

body = {
    'mimeType':'text/csv',
    'title': 'title'
}

# service: your authenticated service
# media: your apiclient.http.MediaFileUpload object, with 'text/csv' mimeType
req = service.files().insert(media_body=media, body=body)

# patch the uri to ensure conversion, as the documented kwarg seems to be borked.
# you may need to use '?convert=true' depending on the uri, not taking that into
# account here for sake of simplicity.
req.uri = req.uri + '&convert=true'

# now we can execute the response.
resp = req.execute()

# should be OK
assert resp['mimeType'] == u'application/vnd.google-apps.spreadsheet'
7
votes

Java :

    //Insert a file  
    File body = new File();
    body.setTitle("CSV");
    body.setDescription("A test document");
    body.setMimeType("text/csv");

    java.io.File fileContent = new java.io.File("document.csv");
    FileContent mediaContent = new FileContent("text/csv", fileContent);

    Insert insert = service.files().insert(body, mediaContent);
    insert.setConvert(true);
    File file = insert.execute();
    System.out.println("File ID: " + file.getId());
0
votes