我正在尝试用Python & requests库替换curl。使用curl,我可以使用curl -T选项将单个XML文件上传到REST服务器。我无法对requests库做同样的事情。
一个基本的场景是:
payload = '<person test="10"><first>Carl</first><last>Sagan</last></person>'
headers = {'content-type': 'application/xml'}
r = requests.put(url, data=payload, headers=headers, auth=HTTPDigestAuth("*", "*"))当我通过打开一个XML文件将有效负载更改为更大的字符串时,.put方法挂起(我使用编解码器库来获得正确的unicode字符串)。例如,对于66KB的文件:
xmlfile = codecs.open('trb-1996-219.xml', 'r', 'utf-8')
headers = {'content-type': 'application/xml'}
content = xmlfile.read()
r = requests.put(url, data=content, headers=headers, auth=HTTPDigestAuth("*", "*"))我一直在考虑使用multipart选项(文件),但服务器似乎不喜欢这样。
所以我想知道是否有一种方法可以在Python请求库中模拟curl -T行为。
更新1:程序在textmate中挂起,但在命令行中抛出UnicodeEncodeError错误。看起来这一定是问题所在。所以问题是:有没有一种方法可以将unicode字符串与请求库一起发送到服务器?
更新2:多亏了Martijn的评论,UnicodeEncodeError消失了,但新的问题出现了。对于文字(ASCII) XML字符串,日志记录显示以下行:
2012-11-11 15:55:05,154 INFO Starting new HTTP connection (1): my.ip.address
2012-11-11 15:55:05,294 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 401 211
2012-11-11 15:55:05,430 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 201 0服务器似乎总是退回第一次身份验证尝试(?)然后再接受第二个。
通过将文件对象(open('trb-1996-219.xml','rb'))传递给data,日志文件显示:
2012-11-11 15:50:54,309 INFO Starting new HTTP connection (1): my.ip.address
2012-11-11 15:50:55,105 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 401 211
2012-11-11 15:51:25,603 WARNING Retrying (0 attempts remain) after connection broken by 'BadStatusLine("''",)': /v1/documents?uri=/example/test.xml因此,第一次尝试会像以前一样被阻止,但不会进行第二次尝试。
根据Martijn (下面)的说法,第二个问题可以通过故障服务器(空行)来解释。我会调查这个问题,但如果有人有解决办法(除了使用curl),我不介意听到它。
我仍然对requests库对于小字符串和文件对象的行为如此不同感到惊讶。文件对象在到达服务器之前不是序列化的吗?
发布于 2012-11-11 22:01:12
要放入大文件,请不要将它们读入内存。只需将文件作为data关键字传递即可:
xmlfile = open('trb-1996-219.xml', 'rb')
headers = {'content-type': 'application/xml'}
r = requests.put(url, data=xmlfile, headers=headers, auth=HTTPDigestAuth("*", "*"))此外,您以unicode格式打开文件(从UTF-8解码它)。因为您将把它发送到远程服务器,所以您需要原始字节,而不是Unicode值,您应该以二进制格式打开该文件。
发布于 2013-05-17 16:14:12
摘要身份验证始终要求您至少向服务器发出两个请求。第一个请求不包含任何身份验证数据。第一个请求将失败,并返回一个401 "Authorization required“响应码和一个用于散列您的密码等的摘要挑战(称为This )(确切的细节在这里无关紧要)。这用于向服务器发出包含您的凭据的第二个请求,该凭据与质询一起散列。
问题出在这两步身份验证中:您的大文件已经与第一个未经授权的请求一起发送(无效发送),但是在第二个请求中,文件对象已经位于EOF位置。由于文件大小也是在第二个请求的Content-length头中发送的,这会导致服务器等待一个永远不会发送的文件。
您可以使用一个请求会话来解决这个问题,并首先出于身份验证的目的发出一个简单的请求(比如GET请求)。然后,使用与第一个请求相同的摘要质询,发出包含实际有效负载的第二个PUT请求。
sess = requests.Session()
sess.auth = HTTPDigestAuth("*", "*")
sess.get(url)
headers = {'content-type': 'application/xml'}
with codecs.open('trb-1996-219.xml', 'r', 'utf-8') as xmlfile:
sess.put(url, data=xmlfile, headers=headers)发布于 2018-07-24 19:09:08
我使用python中的请求通过命令上传了一个XML文件。首先打开文件,使用open() file = open("PIR.xsd") fragment = file.read() file.close()复制请求有效负载中的XML文件的数据并将其发布到payload = {'key':'PFAkrzjmuZR957','xmlFragment':fragment} r = requests.post(URL,data=payload)以检查html验证码print (r.text)
https://stackoverflow.com/questions/13331640
复制相似问题