Getting UnicodeDecodeError when converting a InMemoryUploadedFile to Google MediaUpload

Question:

I am looking for your assistance with the following situation:

I am building a Django Application and I am orchestrating the instance on Google App Engine, Once your Google App Engine instance it’s running it will enter into a "readonly" mode, and therefore Django can no longer write files into the "disk space"

With this mind, The Django application is receiving a ‘File’ submitted through a form, per Django documentation File Uploads are considered an UploadedFile Instance which is then becomes a subclass of InMemoryUploadedFile, If I attempt to pass this object to MediaUpload class I got the following message:

(<class ‘TypeError’>, TypeError(‘expected str, bytes or os.PathLike
object, not InMemoryUploadedFile’), <traceback object at
0x0000014D00669900>)

I need to convert this object to a bytes object as my end goal is to Upload this file into Google Drive using Google APIs

I tried to read the object (assuming the ‘read’ method will return the rawdata (bytes)) but I am getting a Decode error when I do that.

Uploading a File to Google Drive is described in their documentation but it seems the MediaFileUpload Class only accepts Strings/Paths unclear if accepts bytes. Looking at the error message I got "(<class ‘UnicodeDecodeError’>, UnicodeDecodeError…."

Image of the error CMD errorcode.

def expupdate(request):
try:
    creds, _ = google.auth.default()
    service = build('drive', 'v3', credentials=creds)
    myfile = request.FILES['archivo']
    print(myfile.content_type)
    Mtype = myfile.content_type
    print(myfile.size)
    byte_object_after_read = myfile.read()
    media = MediaFileUpload(byte_object_after_read,mimetype=Mtype)
    file_metadata = {'name': 'test.jpeg'}
    file = service.files().create(body=file_metadata, media_body=media,
                                  fields='id').execute()
    fileid = file.get("id")
    print(fileid)

except:
    e = sys.exc_info()
    print('An error occurred:')
    print(e)
Asked By: Eric

||

Answers:

The solution was quite easy.

It turns out Google offers MediaIoBaseUpload class which basically takes as an input a Bytes object and creates the necessary

So the solution to collect a file from a FORM in django using appengine and then upload it to Google Drive without saving the file (manage in memory) is the following

def expupdate(request):
    try:
        creds, _ = google.auth.default()
        service = build('drive', 'v3', credentials=creds)
        myfile = request.FILES['archivo']
        Mtype = myfile.content_type
        fh = myfile.open()
        media = MediaIoBaseUpload(fh,mimetype=Mtype)
        file_metadata = {'name': 'test.jpeg'}
        file = service.files().create(body=file_metadata, 
        media_body=media,fields='id').execute()                      
        fileid = file.get("id")
        print(fileid)

    except:
        e = sys.exc_info()
        print('An error occurred:')
        print(e)
Answered By: Eric