0

My organization is transferring our on-site network drives to Google Drive, and I'm hoping to automate the process some. Not a developer by trade, but I do have programming experience. Never worked with Python or the Google API before but I enjoy a challenge. Got a bit stuck along the way though - I got it to cycle through all the files and directories, and I think I even found a way to get it to map the entire file system correctly. Oddly I thought this would be a common thing to do but I haven't found any code that does it. If you know of a way to copy a whole directory to Google Drive so all the subdirectories are preserved let me know; I made my own and it's kind of a kludge. When I ran it though, it worked for certain file types but crashed with an UnknownFileType error if it encountered a file type that wasn't something common like a txt or docx or xlsx. Obviously the people who need their files transferred over are going to have files of all types, so this simply won't do. Not sure how to address it though. I think I could make a single file work if I set the mimeType metadata but if it's running on multiple files I can't set the mimeType by hand. Maybe there's a different method of uploading the files that can handle any type without needing to know the mimeType? Since this is my first experience with Python or the Google API I mostly copied the code they had on their site and some I found in other locations, then edited it to cycle through all of the files I need. The upload won't even work on one file if it's a strange extension though. Hoping you all can find what's wrong. Here's the pertinent chunk of code.


for filename in filenames:
            print("Uploading file " + filename + " to " + folnames[i])
            file_metadata = {'name': filename,
                         'parents' : [folids[i]]}
            file = service.files().create(body=file_metadata,
                                        media_body=dirpath + "\\" + filename,
                                        fields='id').execute()
            print("Upload Complete")

Any help is appreciated. Thank you!

Edit: I'm posting the full code for the mini program I made to test a single file upload. File names changed to protect privacy

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive']

def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)


    file_metadata = {'name': 'FILENAME'}
    file = service.files().create(body=file_metadata,
                                        media_body='FILEPATH',
                                        fields='id').execute()
    print ("File ID: %s" % file.get('id'))

if __name__ == '__main__':
    main()

Steve
  • 1
  • 1
  • 1
    Please indicate the library you are using/importing in Python, this code is a little ambiguous. – Mohamed Moselhy May 27 '20 at 04:50
  • Have a look [here](https://stackoverflow.com/questions/43580/how-to-find-the-mime-type-of-a-file-in-python) for suggestions on how to find out the mimeType. – ziganotschka May 27 '20 at 09:04
  • Thank you, but getting the mimetype (it was None apparently) didn't help and the upload still crashes because of an UnknownFileType error. I suspect I may need to do a different sort of upload command. – Steve May 27 '20 at 14:27

1 Answers1

0

Got it working by using MimeTypes to guess the mimetype and MediaFileUpload for the media body. Thanks everyone for your help and suggestions.

---
from __future__ import print_function
import pickle
import mimetypes
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
from apiclient.http import MediaFileUpload

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive']

def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)



    mime = mimetypes.MimeTypes().guess_type("FILE")[1]
    file_metadata = {'name': 'NAME',
                     'mimeType': mime}
    media = MediaFileUpload('FILE', mimetype = mime)
    file = service.files().create(body=file_metadata,
                                        media_body= media,
                                        fields='id').execute()
    print ("File ID: %s" % file.get('id'))

if __name__ == '__main__':
    main()
---
Steve
  • 1
  • 1