Craig
Craig

Reputation: 4409

HttpError 400 when requesting https://www.googleapis.com/upload/drive/v2/files/... returned "Invalid Upload Request"

Not sure what is going on under the API here, but from my debug output, everything looks okay. It is passing an ID to a valid file and so forth. Is there any way to enable debug output in the Google SDK?

I see a couple of warnings before the HTTP error:

WARNING:oauth2client.util:new_request() takes at most 1 positional argument (2 given)
WARNING:oauth2client.util:new_request() takes at most 1 positional argument (2 given)

Here is the code:

def update(self, path, properties, media_body = None):
    info = self.stat(path)

    if not info:
        debug("No such file: %s" % path)
        return None

    # Merge properties
    for k, v in properties.iteritems():
        # Do not update the ID, always use the path obtained ID.
        if k == 'id': continue

        setattr(info, k, v)

    try:
        debug("Updating: %s" % info)
        return self.service().files().update(
            fileId = info.id,
            body = info.dict(),
            media_body = media_body
        ).execute()
    except Exception, e:
        debug("Update failed: %s" % str(e))
        debug.stack()
        return None

Okay, this function is called via a file class (either local or remote). In this case, it is the remote file class calling this function, providing a reference to the local file class uploader (media_upload):

So in the remote file class, I have implemented this method. The Drive() class is my own wrapper for the Google API:

def _updateFile(self, path, src):
    debug("Updating remote file: %s" % path)

    if GsyncOptions.dry_run: return

    drive = Drive()
    info = drive.update(path, src.getInfo(), src.getUploader())

    if info is None:
        debug("Update failed")

The 'src' variable is a reference to another file class (the local file). It calls getUploader to pass a reference to the uploader. This is implemented as follows:

def getUploader(self, path = None):
    info = self.getInfo(path)
    if info is None:
        raise Exception("Could not obtain file information: %s" % path)

    path = self.getPath(path)

    f = open(path, "r")
    if f is None:
        raise Exception("Open failed: %s" % path)

    from apiclient.http import MediaIOBaseUpload

    return MediaIoBaseUpload(f, info.mimeType, resumable=True)

Upvotes: 2

Views: 1520

Answers (2)

Craig
Craig

Reputation: 4409

The problem seemed to be that the insert() API method for creating a document, requires a defined value for the document body (or media_body). I initially created the document empty, providing no document body at all, essentially leaving it as None. This created the scenario where I had a document on the Drive that I couldn't update. By creating the document with an empty body, the updates then started working:

return self.service().files().insert(
    body = info.dict(),
    # An empty media_body.
    media_body = ""
).execute()

Upvotes: 0

pinoyyid
pinoyyid

Reputation: 22316

To answer the "Is there any way to enable debug output in the Google SDK?" part of the question, check out https://developers.google.com/api-client-library/python/guide/logging.

Upvotes: 4

Related Questions