我有兴趣编写一个简短的python脚本,通过POST请求将短二进制文件(.wav / .raw音频)上传到远程服务器。
我用pycurl完成了这个,这使得它非常简单并且产生了一个简洁的脚本;不幸的是,它还要求结束 用户安装了pycurl,我不能依赖它。
我也看过其他帖子中的一些例子,这些例子只依赖于基本库,urllib,urllib2等,但是这些通常看起来相当冗长,这也是我想要避免的。
我想知道是否有任何简洁的例子不需要使用外部库,第三方可以快速轻松地理解 - 即使他们不熟悉python。
我目前使用的是什么,
def upload_wav( wavfile, url=None, **kwargs ):
"""Upload a wav file to the server, return the response."""
class responseCallback:
"""Store the server response."""
def __init__(self):
self.contents=''
def body_callback(self, buf):
self.contents = self.contents + buf
def decode( self ):
self.contents = urllib.unquote(self.contents)
try:
self.contents = simplejson.loads(self.contents)
except:
return self.contents
t = responseCallback()
c = pycurl.Curl()
c.setopt(c.POST,1)
c.setopt(c.WRITEFUNCTION, t.body_callback)
c.setopt(c.URL,url)
postdict = [
('userfile',(c.FORM_FILE,wavfile)), #wav file to post
]
#If there are extra keyword args add them to the postdict
for key in kwargs:
postdict.append( (key,kwargs[key]) )
c.setopt(c.HTTPPOST,postdict)
c.setopt(c.VERBOSE,verbose)
c.perform()
c.close()
t.decode()
return t.contents
这不完全正确,但它给了你一般的想法。它很好用,第三方很容易理解,但它需要pycurl。
答案 0 :(得分:4)
发布文件需要multipart/form-data
编码,据我所知,使用stdlib执行此操作并不简单(即单行或其他)。但正如你所提到的,那里有很多食谱。
虽然它们看起来很冗长,但是你的用例表明你可能只需将它封装到一个函数或类中,而不用担心太多,对吧?看一下ActiveState上的食谱,并阅读建议的评论:
或者看看这个PyMOTW中的MultiPartForm
类,它似乎非常可重用:
我相信两者都处理二进制文件。
答案 1 :(得分:2)
我今天遇到了类似的问题,在尝试了pycurl和multipart / form-data之后,我决定阅读python httplib / urllib2源代码以找出答案,我确实得到了一个比较好的解决方案:
以下是代码:
import urllib2, os
image_path = "png\\01.png"
url = 'http://xx.oo.com/webserviceapi/postfile/'
length = os.path.getsize(image_path)
png_data = open(image_path, "rb")
request = urllib2.Request(url, data=png_data)
request.add_header('Cache-Control', 'no-cache')
request.add_header('Content-Length', '%d' % length)
request.add_header('Content-Type', 'image/png')
res = urllib2.urlopen(request).read().strip()
return res
请参阅我的博文:http://www.2maomao.com/blog/python-http-post-a-binary-file-using-urllib2/
答案 2 :(得分:2)
我知道这是一个旧的旧堆栈,但我有一个不同的解决方案。
如果你经历了构建所有魔术标题和所有内容的麻烦,并且只是UPSET,突然一个二进制文件无法通过,因为python库是卑鄙的..你可以修补一个解决方案..
import httplib
class HTTPSConnection(httplib.HTTPSConnection):
def _send_output(self, message_body=None):
self._buffer.extend(("",""))
msg = "\r\n".join(self._buffer)
del self._buffer[:]
self.send(msg)
if message_body is not None:
self.send(message_body)
httplib.HTTPSConnection = HTTPSConnection
如果您使用HTTP://而不是HTTPS://则使用HTTPConnection替换上面的所有HTTPSConnection实例。
在人们对我不满之前,是的,这是一个糟糕的解决方案,但它是一种修复现有代码的方法,你真的不想重新设计以其他方式去做。
为什么要修复它?去看看原始的Python源代码,httplib.py文件。
答案 3 :(得分:1)
urllib如何更加冗长?除了从
开始,你基本上以同样的方式构建postdictpostdict = [ ('userfile', open(wavfile, 'rb').read()) ]
一旦你发布了postdict,
resp = urllib.urlopen(url, urllib.urlencode(postdict))
然后你得到并保存resp.read()
并且可能取消引用并在需要时尝试JSON加载。看起来它实际上会更短!那我错过了什么......?
答案 4 :(得分:0)
urllib.urlencode不喜欢某种二进制数据。