使用Python curl提交文件时的问题
#!/usr/bin/python
import pycurl
import re
import StringIO
#CONSTANTS
URL = "http://www.imagehost.org"
FILE = "/datos/poop1.jpg"
POST_DATA = [("a", "upload"), ("file[]", (pycurl.FORM_FILE, FILE))]
buffer = StringIO.StringIO()
c = pycurl.Curl()
c.setopt( c.URL, URL )
c.setopt( c.POST, 1 )
c.setopt( c.POSTFIELDS, POST_DATA )
##c.setopt( c.HTTPPOST, POST_DATA )
c.setopt( c.USERAGENT,'Curl')
c.setopt( c.WRITEFUNCTION, buffer.write)
c.setopt(pycurl.VERBOSE, 1)
c.perform()
c.close()
#c.setopt(c.PROXY, proxyHostAndPort)
#c.setopt(c.PROXYUSERPWD, proxyAuthentication)
parse = buffer.getvalue()
pattern = re.compile('/<td nowrap="nowrap">(.+)<\/td>\s*<td class="link"><input.+value="([^"]+)" \/><\/td>/i')
result = re.search(pattern, parse)
print result
问题出在如何进行数据提交的方式上。
c.setopt( c.POSTFIELDS, POST_DATA ) 这个方法不接受列表,那我该怎么做才能添加一个列表呢?
而 c.setopt( c.HTTPPOST, POST_DATA ) 则会丢失:
Traceback (most recent call last):
File "pymage", line 26, in <module>
c.perform() pycurl.error: (26, 'failed creating formpost data')
更新:
-----------------------------15758382912173403811539561297\r\nContent-Disposition: form-data; name="a"\r\n\r\nupload\r\n-----------------------------15758382912173403811539561297\r\nContent-Disposition: form-data; name="file[]"; filename="Datos_Pegados_0a17.jpg"\r\nContent-Type: image/jpeg\r\n\r\nÿØÿà
这是我使用 tamper data 得到的结果。
有趣的部分是提交的数据:
form-data; name="a"\r\n\r\nupload\r\n
form-data; name="file[]"
所以...你是说 POST_DATA 应该是 'a=upload&file[]=FILE' 吗?
更新2:
<form method="post" action="/" enctype="multipart/form-data" onsubmit="javascript:Upload(); return true;">
<input type="hidden" name="a" value="upload" />
<td class="left">File:</td>
td class="right"><input name="file[]" type="file" size="20" /></td>
这是代码...
现在表单数据的配置可以正常工作了,但我觉得文件没有上传成功。
c.setopt( c.POSTFIELDS, 'a=upload&file[]=/datos/poop1.jpg' )
我得到的是:
* About to connect() to www.imagehost.org port 80 (#0)
* Trying 74.63.87.74... * connected
* Connected to www.imagehost.org (74.63.87.74) port 80 (#0)
> POST / HTTP/1.1
User-Agent: Curl
Host: www.imagehost.org
Accept: */*
Content-Length: 32
Content-Type: application/x-www-form-urlencoded
< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Date: Wed, 25 Mar 2009 06:53:49 GMT
< Content-Type: text/html
< Server: nginx/0.7.11
< Set-Cookie: userhash=7c09b97cc70c8c133c850a3e744b416e; expires=Thu, 25-Mar-2010 06:53:49 GMT; path=/; domain=.imagehost.org; httponly
<
* Connection #0 to host www.imagehost.org left intact
* Closing connection #0
3 个回答
错误26(在“pycurl.error: (26, '创建表单数据失败')”中)意味着你指定的要上传的文件名不存在。我之前也遇到过这个错误,确实是这个问题。你可以查看curl的源代码,里面有生成错误26的地方。
pycurl的说明书上对此没有说得很清楚,但HTTPPOST这个选项可以接受一个包含多个元组的列表,每个元组的长度都是两个元素。每个元组的第一个元素是表单字段的名称,第二个元素是这个字段的值。
不过,值也可以是一个元组。这个元组必须包含与该字段相关的数据对:比如(表单选项,选项值,表单选项,选项值,等等等等)。
举个例子,如果有一个包含三个字段的多部分表单,最后一个字段是文件上传的,我们可以设置文件名和文件类型:
c = pycurl.Curl()
c.setopt(c.URL, base_url + 'upload.cgi')
c.setopt(c.HTTPPOST,[ ("fieldname1", "value1"),
("fieldname2", "value2"),
("uploadfieldname",
(c.FORM_FILE, local_filename,
c.FORM_CONTENTTYPE, "application/x-gzip"))
])
你可以在curl_formadd()的C API文档中找到相关选项:http://curl.haxx.se/libcurl/c/curl_formadd.html,不过从pycurl的源代码来看,似乎只支持FORM_FILE、FORM_FILENAME、FORM_CONTENTTYPE和FORM_COPYCONTENTS这些选项。