【问题标题】:How to upload a file to Google Drive using a Python script?如何使用 Python 脚本将文件上传到 Google Drive?
【发布时间】:2018-01-24 21:18:39
【问题描述】:

我需要从一些 linux 服务器将各种文件类型备份到 GDrive(不仅仅是那些可转换为 GDocs 格式的文件)。

使用 python 脚本最简单、最优雅的方法是什么?与 GDocs 有关的任何解决方案都适用吗?

【问题讨论】:

  • 2016年上传到g盘的方式是什么?

标签: python backup google-docs-api google-drive-api


【解决方案1】:

您可以使用 Documents List API 编写写入 Drive 的脚本:

https://developers.google.com/google-apps/documents-list/

Documents List API 和 Drive API 都与相同的资源(即相同的文档和文件)交互。

Python 客户端库中的此示例显示了如何将未转换的文件上传到云端硬盘:

http://code.google.com/p/gdata-python-client/source/browse/samples/docs/docs_v3_example.py#180

【讨论】:

【解决方案2】:

可以在此处找到使用 python 将文件保存到谷歌驱动器的当前文档: https://developers.google.com/drive/v3/web/manage-uploads

但是,google drive api 处理文档存储和检索的方式并不遵循与 POSIX 文件系统相同的架构。因此,如果您希望在 linux 文件系统上保留嵌套文件的层次结构,则需要编写大量自定义代码,以便将父目录保留在 google 驱动器上。

最重要的是,谷歌很难获得对普通驱动器帐户的写入权限。您的权限范围必须包括以下链接:https://www.googleapis.com/auth/drive 并且要获得访问用户普通帐户的令牌,该用户必须首先 join a group 提供对未审核应用程序的访问权限。并且任何创建的 oauth 令牌都有有限的保质期。

但是,如果您获得访问令牌,则以下脚本应允许您将本地计算机上的任何文件保存到 google 驱动器上的相同(相对)路径。

def migrate(file_path, access_token, drive_space='drive'):

    '''
        a method to save a posix file architecture to google drive

    NOTE:   to write to a google drive account using a non-approved app,
            the oauth2 grantee account must also join this google group
            https://groups.google.com/forum/#!forum/risky-access-by-unreviewed-apps

    :param file_path: string with path to local file 
    :param access_token: string with oauth2 access token grant to write to google drive
    :param drive_space: string with name of space to write to (drive, appDataFolder, photos)
    :return: string with id of file on google drive
    '''

# construct drive client
    import httplib2
    from googleapiclient import discovery
    from oauth2client.client import AccessTokenCredentials
    google_credentials = AccessTokenCredentials(access_token, 'my-user-agent/1.0')
    google_http = httplib2.Http()
    google_http = google_credentials.authorize(google_http)
    google_drive = discovery.build('drive', 'v3', http=google_http)
    drive_client = google_drive.files()

# prepare file body
    from googleapiclient.http import MediaFileUpload
    media_body = MediaFileUpload(filename=file_path, resumable=True)

# determine file modified time
    import os
    from datetime import datetime
    modified_epoch = os.path.getmtime(file_path)
    modified_time = datetime.utcfromtimestamp(modified_epoch).isoformat()

# determine path segments
    path_segments = file_path.split(os.sep)

# construct upload kwargs
    create_kwargs = {
        'body': {
            'name': path_segments.pop(),
            'modifiedTime': modified_time
        },
        'media_body': media_body,
        'fields': 'id'
    }

# walk through parent directories
    parent_id = ''
    if path_segments:

    # construct query and creation arguments
        walk_folders = True
        folder_kwargs = {
            'body': {
                'name': '',
                'mimeType' : 'application/vnd.google-apps.folder'
            },
            'fields': 'id'
        }
        query_kwargs = {
            'spaces': drive_space,
            'fields': 'files(id, parents)'
        }
        while path_segments:
            folder_name = path_segments.pop(0)
            folder_kwargs['body']['name'] = folder_name

    # search for folder id in existing hierarchy
            if walk_folders:
                walk_query = "name = '%s'" % folder_name
                if parent_id:
                    walk_query += "and '%s' in parents" % parent_id
                query_kwargs['q'] = walk_query
                response = drive_client.list(**query_kwargs).execute()
                file_list = response.get('files', [])
            else:
                file_list = []
            if file_list:
                parent_id = file_list[0].get('id')

    # or create folder
    # https://developers.google.com/drive/v3/web/folder
            else:
                if not parent_id:
                    if drive_space == 'appDataFolder':
                        folder_kwargs['body']['parents'] = [ drive_space ]
                    else:
                        del folder_kwargs['body']['parents']
                else:
                    folder_kwargs['body']['parents'] = [parent_id]
                response = drive_client.create(**folder_kwargs).execute()
                parent_id = response.get('id')
                walk_folders = False

# add parent id to file creation kwargs
    if parent_id:
        create_kwargs['body']['parents'] = [parent_id]
    elif drive_space == 'appDataFolder':
        create_kwargs['body']['parents'] = [drive_space] 

# send create request
    file = drive_client.create(**create_kwargs).execute()
    file_id = file.get('id')

    return file_id

PS。我已经从labpack python 模块修改了这个脚本。由 rcj1492 编写的模块中有一个名为 driveClient 的类,它以保留 POSIX 文件系统的方式处理保存、加载、搜索和删除谷歌驱动器上的文件。

from labpack.storage.google.drive import driveClient

【讨论】:

    【解决方案3】:

    我发现PyDrive 可以优雅地处理 Drive API,它也有很棒的documentation(尤其是引导用户通过身份验证部分)。

    编辑:将其与Automating pydrive verification processPydrive google drive automate authentication 上的材料结合起来,就可以制作出一些很棒的文档来让事情顺利进行。希望它可以帮助那些对从哪里开始感到困惑的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 2022-12-20
      • 2019-11-23
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      相关资源
      最近更新 更多