使用Mirror API和Python将图像附加到静态卡中

时间:2014-05-30 11:58:08

标签: python django google-glass python-requests google-mirror-api

我正在尝试将项目卡插入时间轴,并将图像作为附件。

如果我尝试插入一个项目,那就顺利了:

def notify_card(my_user, card=None):
    payload = card
    headers = {'Content-Type': 'application/json',
               'Authorization': 'Bearer {0}'.format(my_user.mirror_access_token)}
    url = OAUTH_API_BASE_URL + '/mirror/v1/timeline'
    r = requests.post(url, data=payload, headers=headers)
    if r.status_code == 401:
        new_access_token = __refresh_token(my_user.mirror_refresh_token)
        __create_or_update_user(access_token=new_access_token, refresh_token=user_vademecum.mirror_refresh_token)
        headers = {'Content-Type': 'application/json',
               'Authorization': 'Bearer {0}'.format(new_access_token)}
        r = requests.post(url, data=payload, headers=headers)

这样可行,将卡插入时间线。

现在出现问题,当我想上传图片时:

# Send media
import os
module_dir = os.path.dirname(__file__)  # get current directory
file_path = os.path.join(module_dir, 'bodegon.jpg')
file = {'bodegon.jpg': ('bodegon.jpg', open(file_path, 'rb'), 'image/jpg')}
headers = {
           'Authorization': 'Bearer {0}'.format(my_user.mirror_access_token)}
url = OAUTH_API_BASE_URL + 'upload/mirror/v1/timeline?uploadType=multipart'

r = requests.post(url, data={"message": {"bundleId": "0000001"}}, files=file, headers=headers)
print r.text

此代码返回错误消息:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "badContent",
    "message": "Media type 'application/octet-stream' is not supported. Valid media types: [image/*, audio/*, video/*]"
   }
  ],
  "code": 400,
  "message": "Media type 'application/octet-stream' is not supported. Valid media types: [image/*, audio/*, video/*]"
 }
}

如果我手动设置内容类型:

headers = {'content-type': 'image/jpg',
           'Authorization': 'Bearer {0}'.format(my_user.mirror_access_token)}

返回此消息:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "required",
    "message": "Required"
   }
  ],
  "code": 400,
  "message": "Required"
 }
}

另外,我已尝试将媒体发送到此网址:

  

https://www.googleapis.com/upload/mirror/v1/timeline?uploadType=media

而不是

  

https://www.googleapis.com/upload/mirror/v1/timeline?uploadType=multipart

要使用简单上传进行上传: https://developers.google.com/glass/media-upload

我做错了什么?

2 个答案:

答案 0 :(得分:2)

使用您提供的代码,请求将生成一个大致类似的请求主体:

--{boundary}
Content-Disposition: form-data; message="message"


bundleId


--{boundary}

Content-Disposition: form-data; name="bodegon.jpg"



{file contents}

--{boundary}--

请注意,您为bundleId指定的ID不会显示。这意味着你可能希望它是JSON编码的数据,正如@Prison在他的回答中所暗示的那样。根据您的问题进一步判断,您需要为上传的文件部分提供Content-Type。这可以这样解决:

import json
r = requests.post(url, files={"message": (, json.dumps({"bundleId": "0000001"}, 'application/json'), 'file': ('filename.jpg', file, 'image/jpeg')}, headers=headers)

headers是您指定的原始字典。

此外,如果您要上传非常大的文件,您可能需要考虑不单独使用请求。该文件将完整加载到内存中。在这种情况下,您很可能希望流式传输上传。你可以这样使用requests-toolbelt

import requests
from requests_toolbelt import MultipartEncoder
import json

fields = {
    'message': (, json.dumps({'bundleId': '0000001'}, 'application/json'),
    'file': ('filename.jpg', file, 'image/jpeg')
}

encoder = MultipartEncoder(fields)
headers = {
    'Authorization': 'Bearer <your token>',
    'Content-Type': encoder.content_type
}

r = requests.post(url, data=encoder, headers=headers)

这将处理数据编码并允许将数据流传输到服务器。

注意我没有使用文档检查表单部分的名称,因此使用'file'可能不正确。我鼓励你自己调查一下。

答案 1 :(得分:1)

对于初学者,您可能需要考虑使用Google Client Library for Python。它包含了处理Mirror APIs以及执行Media Uploads的一般情况的具体方法。

如果您只是尝试使用附件创建时间轴项目,这可能是最简单的。请参阅https://developers.google.com/glass/v1/reference/timeline/insert#examples上的示例,然后单击Python选项卡。

如果您真的开始直接使用HTTP方法,则需要明确为什么要使用简单上传方法(uploadType = media)与多部分上传方法(uploadType = multipart)。简单上传需要您还调用timeline.attachment来指定附件的元数据,而多部分版本允许您同时上传两者。

使用简单方法,您应该能够使用image / jpeg的内容类型和包含图像数据的正文进行POST。这很简单。可以这么说。

使用multipart方法,您必须处理多种内容类型。您拥有整体的内容类型,其类型为&#34;多部分相关&#34;并包括有关每个部分之间的边界标记的信息。每个部分都有一个内容类型 - 第一部分是&#34; application / json&#34;并包含元数据,而第二部分的类型为&#34; image / jpeg&#34;并包含图像体。它可能看起来像这样:

POST /upload/mirror/v1/timeline?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <your_auth_token>
Content-Type: multipart/related; boundary="foo_bar_baz"
Content-Length: <number_of_bytes_in_entire_request_body>

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{
  "text": "Hello world!"
}

--foo_bar_baz
Content-Type: image/jpeg

<JPEG data>

--foo_bar_baz--

你需要自己建立这个身体。