在上一篇博文中
http://blog.chinaunix.net/space.php?uid=1721137&do=blog&id=348702,讲解了如何使用pycurl和poster进行http post upload files,这仅仅是使用POST方法上传文件,但在实际应用中,我遇到了这样一个问题,倘若有个form,里面既有输入框(FIELDS),又有上传按钮(FILES)的话,那么我们就需要同时POST fields和files,如何做呢?
假如我们有待上传的参数:
- params = {
-
'email': 'example@example.com'
-
'password': 'secret'
-
'caption': 'caption text here'
-
'file': user upload file
-
}
先来看看pycurl:
- from urllib import urlencode
- import pycurl
- c = pycurl.Curl()
-
c.setopt(pycurl.URL, '')
-
c.setopt(pycurl.POST, 1) # POST method
-
c.setopt(pycurl.POSTFIELDS, urlencode(params)) # POST fields except file
-
c.setopt(pycurl.HTTPPOST, [('files', (pycurl.FORM_FILE, '/path/to/uploadfile'))]) # POST file using multipart/form-data
- c.perform()
实践中发现上面的代码并不能正确地工作,也就是pycurl并不能很好地处理同时post fields and files的情况,因为post fields使用‘application/x-www-form-urlencoded’编码,而post files使用'multipart/form-data'编码,所以我们需要使用另外一个更符合我们需求的模块poster。
poster模块能够很好地为我们解决同时post fields and files的问题,只需要简单的几行代码便能完成工作,这里面有个细节需要注意(我遇到的),如果k-v参数里有v是None的,需要将其删除,否则poster会报错。
- from poster.encode import multipart_encode
-
from poster.streaminghttp import register_openers
-
import urllib2
- params = {
- 'email': 'example@example.com'
- 'password': 'secret'
- 'caption': None
- 'file': open('/path/to/file', 'rb')
- }
-
# 如果params['caption']==None,需要将caption剔除
-
params = dict((k, v) for k, v in params.iteritems() if v)
-
-
register_openers()
-
datagen, headers = multipart_encode(params) # 很简单地将fields and files一起进行encode
-
request = urllib2.Request('', datagen, headers)
-
try:
-
urllib2.urlopen(request)
-
except urllib2.HTTPError, e:
-
print e.code # http status code
总结:以后如果再遇到需要同时post fields and files的情况,就是用poster模块。
阅读(5256) | 评论(0) | 转发(0) |