使用Python请求发布到cloudappapi(AWS)

2024-09-30 08:28:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我花了几天时间试图找出如何在Python中将图像发布到CloudApp,使用请求访问{a2}。我可以使用pycloudapp,它使用Poster来完成,但是我想学习如何处理请求。在

我一直在尝试使用InspectB.in来比较我的脚本和pycloudapp发布的内容,试图找出差异。似乎不多,但显然存在的少数是重要的。对于我当前的代码,我得到了一个服务器端错误(500),这是令人沮丧的。因为基于海报的代码可以工作,所以我希望找到一种方法让请求也能工作,尽管我认为这可能不可行。在

CloudApp使用amazonweb存储,我知道AWS必须最后使用“file”参数。到目前为止,我已经尝试过几种使用data = collections.OrderedDict(sorted(upload_values)); data['file'] = open(last_pic, 'rb')而不是使用单独的data和{}字典(如建议的here)的不同排列。我查了files字典,有没有文件名。在

这是我的代码:

#!/usr/bin/env python

import requests
import os

last_pic = '/.../image.jpg'

USER = 'email@email.com'
PASS = 'mypass'

AUTH_URL = 'http://my.cl.ly'
API_URL = 'http://my.cl.ly/items/new'

s = requests.Session()
s.auth = requests.auth.HTTPDigestAuth(USER, PASS)
s.headers.update({'Accept': 'application/json'})

upload_request = s.get(API_URL)

upload_values = upload_request.json()['params']

filename = os.path.basename(last_pic)
upload_values['key'] = upload_values['key'].replace(r'${filename}', filename)

files = {'file': open(last_pic, 'rb')}

stuff = requests.post(upload_request.json()['url'], data=upload_values, files=files)
print(stuff.text)

根据检查B.in,工作(pycloudapp)帖子和我的帖子之间的唯一区别是:

pycloudapp post主体中的每个参数都有Content-Type: text/plain; charset=utf-8,但在我的代码中没有。例如:

^{pr2}$

与我的对比:

--b1892e959d124887a61143dd2b468579
Content-Disposition: form-data; name="acl"

public-read

文件数据不同。在

pycloudapp:

--d5e0c013a6de4105b07ac844eea4da6e
Content-Disposition: form-data; name="file"
Content-Type: text/plain; charset=utf-8

����JFIFHH���ICC_PROFILE�applmntrRGB XYZ �...

与我的对比:

--b1892e959d124887a61143dd2b468579
Content-Disposition: form-data; name="file"; filename="20130608-ScreenShot-180.jpg"
Content-Type: image/jpeg

����JFIFHH���ICC_PROFILE�applmntrRGB XYZ �...

标题基本相同,除了:

pycloudapp:

Accept: application/json
Accept-Encoding: identity

我的:

Accept: */*
Accept-Encoding: gzip, deflate, compress

具体来说,这两个都成功注册为Content-Type: multipart/form-data

考虑到accept头可能是重要的区别,我尝试添加headers = {'accept': 'application/json', 'content-type': 'multipart/form-data'}(以及这两个单独的),但没有成功。不幸的是,如果我修改头,它会覆盖所有的头并丢失多部分编码。在

我还想知道我的文章中的文件Content-Type: image/jpeg与工作帖子中的Content-Type: text/plain; charset=utf-8是否是问题所在。在

很抱歉这么长的帖子,这已经把我逼疯了,谢谢你能提供的任何帮助。在


Tags: 代码formjsondatatypefilescontentrequests
1条回答
网友
1楼 · 发布于 2024-09-30 08:28:28

几天后,我终于解决了这个(简单的)问题。cloudappapi需要对Amazon响应中的“Location”头发出“GET”请求。在

Pycloudapp工作正常,因为它使用return json.load(self.upload_auth_opener.open(request))正确验证了GET响应。在

我不知道为什么我能够在没有任何身份验证的情况下使用Postman正确地发布,不管怎么说,它是正确地跟随GET而没有凭据,即使cloudappapi指定遵循重定向requires authentication。在

我无法正确跟踪请求的重定向,因为我发布的是未经验证的值(如果我继续使用s.post执行Session(),则auth头会抛出错误,因为Amazon并不期望这些值),因此随后的GET也是未经验证的。这场痛苦的一个非常令人困惑的部分是,发布的图片在我的CloudApp帐户中显示的是而不是。然而,我后来发现,我可以手动将亚马逊的回复“位置”粘贴到一个浏览器窗口中,突然,发布的图片出现在我的账户中。这使我意识到POST是不够的;需要一个经过身份验证的GET来完成这个过程。在

然后我发现我没有从requests.post.headers得到任何帮助。花了几分钟时间,才发现它是用重定向的头响应的(它跟踪的GET中的500个错误),而不是POST。一旦我添加了allow_redirects=False,我就可以正确地访问Amazon响应的“Location”头。我刚刚把这个头反馈到我的已验证会话()中,它终于起作用了。在

另一个对这个过程很有帮助的东西是this SO thread,它教会了我logging with Requests。在

希望这个解释有道理,对其他人有帮助。这几天我确实学到了很多东西。我的代码可能还需要改进,我想用urllib.quote_plus但我今天要等8次上传了。在

我的当前代码:

#!/usr/bin/env python

import requests
from collections import OrderedDict
import keyring
import os

last_pic = '/path/to/image.jpg'

USER = 'myemail@email.com'
KEYCHAIN_SERVICE_NAME = 'cloudapp'

# replace with PASS = 'your_password' if you don't use keyring
PASS = keyring.backends.OS_X.Keyring.get_password(KEYCHAIN_SERVICE_NAME, USER)

AUTH_URL = 'http://my.cl.ly'
API_URL = 'http://my.cl.ly/items/new'

s = requests.Session()
s.auth = requests.auth.HTTPDigestAuth(USER, PASS)
s.headers.update({'Accept': 'application/json'})

upload_request = s.get(API_URL)
param_list = []
for key, value in upload_request.json()['params'].items():
    param_list.append((key.encode('utf8'), value.encode('utf8')))
data = OrderedDict(sorted(param_list))

filename = (os.path.basename(last_pic)).encode('utf8')
data['key'] = data['key'].replace(r'${filename}', filename)
files = {'file': (filename, open(last_pic,'rb').read()) }

stuff = requests.post(upload_request.json()['url'], data=data, files=files, allow_redirects=False)

s.get(stuff.headers['Location'])

相关问题 更多 >

    热门问题