Mac*_*Mac 43 python rest post urllib2 redmine
我正在编写一些与redmine接口的代码,我需要上传一些文件作为过程的一部分,但我不知道如何从包含二进制文件的python中执行POST请求.
我试图在这里模仿命令:
curl --data-binary "@image.png" -H "Content-Type: application/octet-stream" -X POST -u login:password http://redmine/uploads.xml
Run Code Online (Sandbox Code Playgroud)
在python(下面)中,它似乎不起作用.我不确定问题是否与编码文件有关,或者标题是否有问题.
import urllib2, os
FilePath = "C:\somefolder\somefile.7z"
FileData = open(FilePath, "rb")
length = os.path.getsize(FilePath)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, 'http://redmine/', 'admin', 'admin')
auth_handler = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
request = urllib2.Request( r'http://redmine/uploads.xml', FileData)
request.add_header('Content-Length', '%d' % length)
request.add_header('Content-Type', 'application/octet-stream')
try:
response = urllib2.urlopen( request)
print response.read()
except urllib2.HTTPError as e:
error_message = e.read()
print error_message
Run Code Online (Sandbox Code Playgroud)
我有权访问服务器,它看起来像编码错误:
...
invalid byte sequence in UTF-8
Line: 1
Position: 624
Last 80 unconsumed characters:
7z¼¯'ÅÐз2^Ôøë4g¸R<süðí6kĤª¶!»=}jcdjSPúá-º#»ÄAtD»H7Ê!æ½]j):
(further down)
Started POST "/uploads.xml" for 192.168.0.117 at 2013-01-16 09:57:49 -0800
Processing by AttachmentsController#upload as XML
WARNING: Can't verify CSRF token authenticity
Current user: anonymous
Filter chain halted as :authorize_global rendered or redirected
Completed 401 Unauthorized in 13ms (ActiveRecord: 3.1ms)
Run Code Online (Sandbox Code Playgroud)
Pio*_*ost 53
基本上你做的是正确的.查看您链接到的redmine文档,似乎url中的点后面的后缀表示发布数据的类型(JSON为.json,XML为.xml),这与您获得的响应一致 - Processing by AttachmentsController#upload as XML
.我想也许文档中有一个错误并发布二进制数据你应该尝试使用http://redmine/uploads
url而不是http://redmine/uploads.xml
.
顺便说一下,我强烈推荐非常好的非常受欢迎的Python 请求库.它比标准库(urllib2)中的要好得多.它也支持身份验证,但为了简洁,我在这里略过了它.
import requests
data = open('./x.png', 'rb').read()
res = requests.post(url='http://httpbin.org/post',
data=data,
headers={'Content-Type': 'application/octet-stream'})
# let's check if what we sent is what we intended to send...
import json
import base64
assert base64.b64decode(res.json()['data'][len('data:application/octet-stream;base64,'):]) == data
Run Code Online (Sandbox Code Playgroud)
UPDATE
要找出为什么这适用于请求而不是urllib2,我们必须检查发送内容的差异.为了看到这一点,我将流量发送到在端口8888上运行的http代理(Fiddler):
使用请求
import requests
data = 'test data'
res = requests.post(url='http://localhost:8888',
data=data,
headers={'Content-Type': 'application/octet-stream'})
Run Code Online (Sandbox Code Playgroud)
我们看
POST http://localhost:8888/ HTTP/1.1
Host: localhost:8888
Content-Length: 9
Content-Type: application/octet-stream
Accept-Encoding: gzip, deflate, compress
Accept: */*
User-Agent: python-requests/1.0.4 CPython/2.7.3 Windows/Vista
test data
Run Code Online (Sandbox Code Playgroud)
并使用urllib2
import urllib2
data = 'test data'
req = urllib2.Request('http://localhost:8888', data)
req.add_header('Content-Length', '%d' % len(data))
req.add_header('Content-Type', 'application/octet-stream')
res = urllib2.urlopen(req)
Run Code Online (Sandbox Code Playgroud)
我们得到
POST http://localhost:8888/ HTTP/1.1
Accept-Encoding: identity
Content-Length: 9
Host: localhost:8888
Content-Type: application/octet-stream
Connection: close
User-Agent: Python-urllib/2.7
test data
Run Code Online (Sandbox Code Playgroud)
我没有看到任何可能导致您观察到不同行为的差异.已经说过,http服务器检查User-Agent
标头并根据其值改变行为并不罕见.尝试逐个更改请求发送的标头,使其与urllib2发送的标头相同,并查看它何时停止工作.
归档时间: |
|
查看次数: |
83612 次 |
最近记录: |