pythongoogle-drive-apipydrivebytesio

Uploading image string to Google Drive using pydrive


I need to upload an image string (as the one you get from requests.get(url).content) to google drive using the PyDrive package. I checked a similar question but the answer accepted there was to save it in a temporary file on a local drive and then upload that.
However, I cannot do that because of local storage and permission restrictions.
The accepted answer was previously to use SetContentString(image_string.decode('utf-8')) since

SetContentString requires a parameter of type str not bytes.

However the error: UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte came up, as in the comments on that answer.
Is there any way to do this without using a temporary file, using PIL/BytesIO/anything that can convert it to be uploaded correctly as a string or somehow using PIL manipulated as an image and uploaded using SetContentFile()?

A basic example of what I'm trying to do is:

img_content = requests.get('https://i.imgur.com/A5gIh7W.jpeg')
file = drive.CreateFile({...})
file.setContentString(img_content.decode('utf-8'))
file.Upload()

Solution

  • When I saw the document (Upload and update file content) of pydrive, it says as follows.

    Managing file content is as easy as managing file metadata. You can set file content with either SetContentFile(filename) or SetContentString(content) and call Upload() just as you did to upload or update file metadata.

    And, I searched about the method for directly uploading the binary data to Google Drive. But, I couldn't find it. From this situation, I thought that there might not be such method. So, in this answer, I would like to propose to upload the binary data using requests module. In this case, the access token is retrieved from the authorization script of pydrive. The sample script is as follows.

    Sample script:

    from pydrive.auth import GoogleAuth
    import io
    import json
    import requests
    
    
    url = 'https://i.imgur.com/A5gIh7W.jpeg' # Please set the direct link of the image file.
    filename = 'sample file' # Please set the filename on Google Drive.
    folder_id = 'root' # Please set the folder ID. The file is put to this folder.
    
    gauth = GoogleAuth()
    gauth.LocalWebserverAuth()
    metadata = {
        "name": filename,
        "parents": [folder_id]
    }
    files = {
        'data': ('metadata', json.dumps(metadata), 'application/json'),
        'file': io.BytesIO(requests.get(url).content)
    }
    r = requests.post(
        "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
        headers={"Authorization": "Bearer " + gauth.credentials.access_token},
        files=files
    )
    print(r.text)
    

    Note:

    References: