发布文件并使用pycurl传递参数

时间:2012-03-05 08:10:04

标签: python rest curl libcurl pycurl

我已经找到了如何使用pycurl进行GET,PUT,DELETE和基本POST。

尽管如此,我无法弄清楚这个curl命令行(对于python来说效果很好)的等价物是什么:

curl -u admin:geoserver -XPOST -H 'Content-type: application/vnd.ogc.sld+xml' 
-d @/Users/rburhum/src/calthorpe/calthorpe/server/calthorpe/media/styles/1_my-scenario
"http://127.0.0.1:8080/geoserver/rest/styles?name=1_my-scenario" -v

I have seen the samples at the repo。尽管如此,传递一个参数(在本例中为 name )和一个要上传的文件似乎不起作用。

对于PUT调用,我已成功使用:

filesize = path.getsize(sldFile)
f = open(sldFile,'rb')

c = pycurl.Curl()

c.setopt(pycurl.HTTPHEADER, ["Content-type: application/vnd.ogc.sld+xml"])
c.setopt(pycurl.USERPWD, GEOSERVER_USER + ':' + GEOSERVER_PASSWORD)    
c.setopt(pycurl.INFILESIZE, filesize)
c.setopt(c.URL, str(GEOSERVER_URL + '/rest/styles/' + path.basename(sldFile)))
c.setopt(pycurl.PUT, 1)
c.setopt(pycurl.INFILE, f)
c.perform()
f.close()
因此,我天真地认为POST等价物将是:

filesize = path.getsize(sldFile)
f = open(sldFile,'rb')

c = pycurl.Curl()

c.setopt(c.URL, str(GEOSERVER_URL + '/rest/styles?name=' + path.basename(sldFile)))
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.HTTPHEADER, ["Content-type: application/vnd.ogc.sld+xml"])
c.setopt(pycurl.USERPWD, GEOSERVER_USER + ':' + GEOSERVER_PASSWORD)    
c.setopt(pycurl.INFILESIZE, filesize)
c.setopt(pycurl.INFILE, f)
c.perform()
f.close()

curl命令的详细输出显示:

(calthorpe_env)rburhum@peru.local~ / src / calthorpe / calthorpe / server / calthorpe       $ calthorpe / server / calthorpe POST -H'Content-type:application / vnd.ogc.sld + xml'       -d @ /用户/ rburhum / src目录/卡索普/卡索普/服务器/卡索普/媒体/风格/ 1_my情景       “http://127.0.0.1:8080/geoserver/rest/styles?name=1_my-scenario”-v       *即将连接()到127.0.0.1端口8080(#0)       *尝试127.0.0.1 ...已连接       *连接到127.0.0.1(127.0.0.1)端口8080(#0)       *服务器使用Basic使用'admin'

进行身份验证
  

POST / geoserver / rest / styles?name = 1_my-scenario HTTP / 1.1   授权:基本YWRtaW46Z2Vvc2VydmVy   User-Agent:curl / 7.21.4(universal-apple-darwin11.0)libcurl / 7.21.4           OpenSSL / 0.9.8r zlib / 1.2.5   主持人:127.0.0.1:8080   接受: /   内容类型:application / vnd.ogc.sld + xml   内容长度:28135   期待:100-continue

>        < HTTP / 1.1 100继续        < HTTP / 1.1 201已创建        <日期:星期一,2012年3月5日07:39:43 GMT        <地点:http://127.0.0.1:8080/geoserver/rest/styles/1_my-scenario        <服务器:Noelios-Restlet-Engine / 1.0..8        <转移编码:分块        <        *连接#0到主机127.0.0.1保持不变        *关闭连接#0

我可以清楚地看到内容长度是正确的。

相反,当我对上面的POST代码进行详细输出时,我可以看到内容长度为-1(因此文件未被传递,服务器返回500)。我已经使用HTTPPOST变量进行了模拟,在某些组合下使内容长度正确,但我仍然无法获得上面的CURL命令的完全等效工作。

1 个答案:

答案 0 :(得分:6)

我必须结合几个例子才能找到正确的组合,当然,我在IRC频道的一些好人那里得到了一些帮助。我能设法让它发挥作用的唯一方法就是对pycurl sample进行略微修改,而这种变化并不像我所描述的那样。

class FileReader:
    def __init__(self, fp):
        self.fp = fp
    def read_callback(self, size):
        return self.fp.read(size)

然后,我会设置这样的调用:

c = pycurl.Curl()
c.setopt(c.URL, str(GEOSERVER_URL + '/rest/styles?name=' + path.basename(sldFile)))
c.setopt(pycurl.POST, 1)
filesize = path.getsize(sldFile)
f = open(sldFile,'rb')
c.setopt(pycurl.POSTFIELDSIZE, filesize)
c.setopt(pycurl.READFUNCTION, FileReader(f).read_callback)
c.setopt(pycurl.HTTPHEADER, ["Content-type: application/vnd.ogc.sld+xml"])
c.setopt(pycurl.USERPWD, GEOSERVER_USER + ':' + GEOSERVER_PASSWORD)

c.perform()
f.close()

请注意,原始样本没有使用POSTFIELDSIZE(只有INFILESIZE),没有它,我无法使其工作。

作为附注,在我的情况下,sldFile已经被软件化,所以不需要urlencode,否则,你可能想要这样做。