8

I'm able to upload a file to Google Drive using the python API as provided in this example by using the MediaUpload class.

But I need to upload a file which is dynamically created and I don't want to save it and open again.

There is no such implementation already existing. This guide says I need to create a subclass of MediaUpload and must fully implement the MediaUpload interface.

I went through the code and it's really confusing. If anyone had already implemented it or could help me with this, please share the code.

Thank you

Jun
  • 2,339
  • 1
  • 20
  • 26
  • If you're talking about file-like I/O, then something like https://docs.python.org/2/library/stringio.html and/or https://docs.python.org/2/library/io.html may help – woozyking Mar 25 '16 at 04:57
  • 2
    Glancing at the docs, it appears that they offer a MediaIoBaseUpload class that supports uploading based on a file type object (a seekable stream). http://google-api-python-client.googlecode.com/hg/docs/epy/apiclient.http.MediaIoBaseUpload-class.html – clockwatcher Mar 25 '16 at 05:01
  • @clockwatcher Thanks for pointing it out. I thought I'd have to rewrite everything again. Figured out how to make it work. :) – Jun Mar 25 '16 at 05:56

2 Answers2

13

Answering my own question

What I wanted to do was to get a file from a url and upload to drive.

Used MediaIoBaseUpload class instead of MediaUpload class.

response = urllib2.urlopen(url)
fh = BytesIO(response.read())
media_body = MediaIoBaseUpload(fh, mimetype='image/jpeg',
              chunksize=1024*1024, resumable=True)
body = {
        'title': 'pic.jpg'
    }
drive_service.files().insert(body=body, media_body=media_body).execute()
Jun
  • 2,339
  • 1
  • 20
  • 26
  • Hi @Jun: I know it has been a long time since you posted this but response.read() will return the entire content of the remote file in one shot ? So this solution will probably not work with very large files without having enough memory. Download the file and then upload it in chunks is more memory efficient at the expense of disk storage. I'm actually looking for a solution to download chunk by chunk from remote url in memory and then upload those in-memory chunks without ever writing them to disk storage. If you had any pointers, please share. Thanks. – user4848830 Mar 14 '21 at 01:19
0

For those looking for a way to upload a file not through a url, but using formdata or any media object/string which is in bytes, here is the sample code.

The following case is, I am sending a docx file from my frontend application using formdata & receiving it on the backend. Now this file, I want to upload to google drive.

The tech stack I'm using is Angular 8 for frontend & Tornado Python for backend.

Backend Python Code:

import io
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseUpload
from gdrive_config import credentials # Import your credentials object created using a service account 
# Refer this link for more info - https://github.com/googleapis/google-api-python-client/blob/master/docs/oauth-server.md

drive_service = build("drive", "v3", credentials=credentials, cache_discovery=False)

file = self.request.files
file_info = file["my_docx_file"][0] # Here "my_docx_file" is the key name you have set in form data

def upload_file(file_info):
    file_name = file_info["filename"]

    file_metadata = {
        "name": file_name,
        "mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", # Mimetype for docx
    }

    media = MediaIoBaseUpload(io.BytesIO(file_info["body"]), # **Pass your bytes object/string here
                              mimetype="application/vnd.google-apps.document", # I'm converting docx to native google docs
                              resumable=True)

    file = drive_service.files().create(body=file_metadata,
                                        media_body=media,
                                        fields="id, name").execute()

    print("Uploaded File '{}' with ID: {}".format(file.get("name"), file.get("id")))

Reference links:

Oauth flow for service accounts - https://github.com/googleapis/google-api-python-client/blob/master/docs/oauth-server.md

Google drive python client docs - https://developers.google.com/resources/api-libraries/documentation/drive/v3/python/latest/drive_v3.files.html

Google drive upload file guide - https://developers.google.com/drive/api/v3/manage-uploads

nikhiljpinto
  • 81
  • 2
  • 5