Python 在没有Google驱动程序UI的情况下将大文件上载到Google Drive的帖子

Python 在没有Google驱动程序UI的情况下将大文件上载到Google Drive的帖子,python,google-app-engine,google-drive-api,Python,Google App Engine,Google Drive Api,我的理解是,要使用API版本2从我自己的应用程序上传一个大文件到Google Drive,我应该发送如下消息。不幸的是,我不知道如何使用Python实现多部分消息的这种格式。有没有人有Python示例代码可以让我走上正确的方向 谢谢, 克里斯 POST/upload/drive/v2/files?uploadType=multipart 授权:持票人 内容长度: 内容类型:多部分/相关;boundary=“” -- 内容类型:application/json {“title”:“test.jp

我的理解是,要使用API版本2从我自己的应用程序上传一个大文件到Google Drive,我应该发送如下消息。不幸的是,我不知道如何使用Python实现多部分消息的这种格式。有没有人有Python示例代码可以让我走上正确的方向

谢谢, 克里斯


POST/upload/drive/v2/files?uploadType=multipart
授权:持票人
内容长度:
内容类型:多部分/相关;boundary=“”
--
内容类型:application/json
{“title”:“test.jpg”,“mimeType”:“image/jpeg”,“parents”:[]}
--
内容类型:图像/jpeg
内容传输编码:base64
----

Google Drive API的参考指南包含多种语言的代码片段,包括所有API端点的Python

对于您的用例,端点有以下答案:

from apiclient import errors
from apiclient.http import MediaFileUpload
# ...

def insert_file(service, title, description, parent_id, mime_type, filename):
  """Insert new file.

  Args:
    service: Drive API service instance.
    title: Title of the file to insert, including the extension.
    description: Description of the file to insert.
    parent_id: Parent folder's ID.
    mime_type: MIME type of the file to insert.
    filename: Filename of the file to insert.
  Returns:
    Inserted file metadata if successful, None otherwise.
  """
  media_body = MediaFileUpload(filename, mimetype=mime_type, resumable=True)
  body = {
    'title': title,
    'description': description,
    'mimeType': mime_type
  }
  # Set the parent folder.
  if parent_id:
    body['parents'] = [{'id': parent_id}]

  try:
    file = service.files().insert(
        body=body,
        media_body=media_body).execute()

    return file
  except errors.HttpError, error:
    print 'An error occured: %s' % error
    return None

GoogleDriveAPI的参考指南包含许多语言的代码片段,包括所有API端点的Python

对于您的用例,端点有以下答案:

from apiclient import errors
from apiclient.http import MediaFileUpload
# ...

def insert_file(service, title, description, parent_id, mime_type, filename):
  """Insert new file.

  Args:
    service: Drive API service instance.
    title: Title of the file to insert, including the extension.
    description: Description of the file to insert.
    parent_id: Parent folder's ID.
    mime_type: MIME type of the file to insert.
    filename: Filename of the file to insert.
  Returns:
    Inserted file metadata if successful, None otherwise.
  """
  media_body = MediaFileUpload(filename, mimetype=mime_type, resumable=True)
  body = {
    'title': title,
    'description': description,
    'mimeType': mime_type
  }
  # Set the parent folder.
  if parent_id:
    body['parents'] = [{'id': parent_id}]

  try:
    file = service.files().insert(
        body=body,
        media_body=media_body).execute()

    return file
  except errors.HttpError, error:
    print 'An error occured: %s' % error
    return None

我在别处找到了答案,这段Python代码生成了问题中显示的消息

url = 'https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart'

boundary = base64.b64encode(uuid.uuid4().bytes)
parts = []
parts.append('--' + boundary)
parts.append('Content-Type: application/json')
parts.append('')
parts.append(json.dumps({
    'title': name,
    'mimeType': 'image/jpeg',
    'parents': [{
        'kind': 'drive#file',
        'id': folderId
        }] if folderId else []
    }))
parts.append('--' + boundary)
parts.append('Content-Type: image/jpeg')
parts.append('Content-Transfer-Encoding: base64')
parts.append('')
parts.append(base64.b64encode(content))
parts.append('--' + boundary + '--')
parts.append('')
body = '\r\n'.join(parts)

headers = {
    'Content-Type': 'multipart/related; boundary="%s"' % boundary,
    'Content-Length': str(len(body)),
    'Authorization': 'Bearer %s' % access_token
    }
response = urlfetch.fetch(url, payload=body, method='POST', headers=headers)
assert response.status_code == 200, '%s - %s' % (response.status_code, response.content)
r = json.loads(response.content)

我在别处找到了答案,这段Python代码生成了问题中显示的消息

url = 'https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart'

boundary = base64.b64encode(uuid.uuid4().bytes)
parts = []
parts.append('--' + boundary)
parts.append('Content-Type: application/json')
parts.append('')
parts.append(json.dumps({
    'title': name,
    'mimeType': 'image/jpeg',
    'parents': [{
        'kind': 'drive#file',
        'id': folderId
        }] if folderId else []
    }))
parts.append('--' + boundary)
parts.append('Content-Type: image/jpeg')
parts.append('Content-Transfer-Encoding: base64')
parts.append('')
parts.append(base64.b64encode(content))
parts.append('--' + boundary + '--')
parts.append('')
body = '\r\n'.join(parts)

headers = {
    'Content-Type': 'multipart/related; boundary="%s"' % boundary,
    'Content-Length': str(len(body)),
    'Authorization': 'Bearer %s' % access_token
    }
response = urlfetch.fetch(url, payload=body, method='POST', headers=headers)
assert response.status_code == 200, '%s - %s' % (response.status_code, response.content)
r = json.loads(response.content)

我熟悉这段代码,以前也试过使用它。当我尝试使用它时,我指定了一个像“test.jpeg”这样的文件名,并得到一个错误,说“test.jpeg”找不到。我该怎么处理文件名?这是上传的文件名吗?或者我想上传的名字?我的理解是,除非您使用multipart POST,否则您必须对API进行两次调用,一次是告诉它您要发布什么,另一次是发布实际数据。您发布的这段代码并没有像我在问题中寻找和描述的那样创建一个多部分POST;如果从内存读取,可以使用其他MediaUPload类型。要执行多部分请求,只需将
resubable
设置为
False
。谢谢Alain,但是如何获取用户从表单上载的文件名?如果从不需要后端逻辑的web表单上载新文件,您可以改为使用更简单的。否则,由于您是从内存(而不是硬盘驱动器)获取blob,因此应该改用类。我希望在不使用选择器的情况下执行此操作,但仍然从本地硬盘驱动器选择文件。可能吗?我熟悉并使用MediaInMemoryPload处理我在应用程序中创建的文件。我熟悉这段代码,以前也尝试过使用它。当我尝试使用它时,我指定了一个像“test.jpeg”这样的文件名,并得到一个错误,说“test.jpeg”找不到。我该怎么处理文件名?这是上传的文件名吗?或者我想上传的名字?我的理解是,除非您使用multipart POST,否则您必须对API进行两次调用,一次是告诉它您要发布什么,另一次是发布实际数据。您发布的这段代码并没有像我在问题中寻找和描述的那样创建一个多部分POST;如果从内存读取,可以使用其他MediaUPload类型。要执行多部分请求,只需将
resubable
设置为
False
。谢谢Alain,但是如何获取用户从表单上载的文件名?如果从不需要后端逻辑的web表单上载新文件,您可以改为使用更简单的。否则,由于您是从内存(而不是硬盘驱动器)获取blob,因此应该改用类。我希望在不使用选择器的情况下执行此操作,但仍然从本地硬盘驱动器选择文件。可能吗?我熟悉并使用MediaInMemoryPload处理我在应用程序中创建的文件。