使用PyCurl从文件对象上载文件

时间:2010-05-19 06:47:27

标签: python pycurl

我正在尝试上传这样的文件:

import pycurl

c = pycurl.Curl()

values = [
     ("name", "tom"),
     ("image", (pycurl.FORM_FILE, "tom.png"))
]

c.setopt(c.URL, "http://upload.com/submit")
c.setopt(c.HTTPPOST, values)
c.perform()
c.close()

这很好用。但是,这仅在文件是本地文件时才有效。如果我要获取图像:

import urllib2
resp = urllib2.urlopen("http://upload.com/people/tom.png")

如何将resp.fp作为文件对象传递而不是将其写入文件并传递文件名?这可能吗?

1 个答案:

答案 0 :(得分:4)

在完美的情况下,基本上可以连接两个流,但它不是一个非常强大的解决方案。有一堆丑陋的边界条件:

  • 响应套接字可能仍然是 接收数据和/或停滞, 从而导致你饿死了 打破POST(因为PycURL不是 期待必须等待数据 超出当前的结束 “文件”)。
  • 响应可能会重置,然后您没有完整的文件,但是您已经发布了大量数据 - 在这种情况下该怎么做?
  • 您使用urllib获取的文件可能是分块编码的,因此您需要对MIME标头执行一些操作以进行重组 - 您不能盲目地转发数据。
  • 你不一定知道你得到的文件有多大,所以很难在POST上提供正确的内容长度,所以你必须写下chunked。
  • 可能还有一些我无法想到的其他问题......

暂时将文件写入磁盘然后在知道完整内容后进行POST后,你会好得多。

如果您确实想要这样做,最好的方法可能是实现您自己的类文件对象,它将管理两个连接之间的桥接(可以正确缓冲,处理解码等)。

编辑:

根据您留下的评论 - 绝对 - 您只需要设置READFUNCTION。查看以下位置的file_upload示例:

http://pycurl.cvs.sourceforge.net/viewvc/pycurl/pycurl/examples/file_upload.py?revision=1.5&view=markup

通过在带有回调的文件对象上创建一个小包装器以从中读取数据,或者如果您不需要进行任何处理,您可以真正地设置READFUNCTION回调。成为fp.read