Загрузка файла из файлового объекта с помощью PyCurl - PullRequest
1 голос
/ 19 мая 2010

Я пытаюсь загрузить файл, подобный этому:

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 Ответ

4 голосов
/ 19 мая 2010

В идеальных ситуациях может быть возможно в принципе соединить два потока, но это не будет очень надежным решением.Существует множество уродливых граничных условий:

  • Возможно, сокет ответа все еще принимает данные и / или останавливается, что приводит к тому, что вы вынуждены голодать и нарушать POST (поскольку PycURL не ожидаетпридется ждать данных за пределами текущего конца «файла»).
  • Ответ может быть сброшен, и тогда у вас не будет полного файла, но вы уже поместили кучу данных - чточто делать в этом случае?
  • Файл, который вы извлекаете с помощью urllib, может быть закодирован, поэтому вам нужно выполнить некоторые операции над заголовками MIME для повторной сборки - вы не можете просто слепо переслать данные.
  • Вы не обязательно знаете, какой размер файла вы получаете, поэтому трудно указать правильную длину содержимого в POST, поэтому вам придется писать кусками.
  • Вероятно, куча других проблем, о которых я не могу вспомнить ...

Вам будет гораздо лучше временно записать файл на диск, а затем отправить его, как только вытеперь у вас есть все.

Если вы действительно хотите это сделать, лучшим способом будет, вероятно, реализовать собственный файловый объект, который будет управлять мостом между двумя соединениями (может правильно буферизовать, обрабатыватьрасшифровка и т. д.).

РЕДАКТИРОВАТЬ:

Исходя из оставленного вами комментария - абсолютно точно - вам просто нужно установить READFUNCTION.Посмотрите пример file_upload по адресу:

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

Он делает именно это, создавая крошечную оболочку для объекта файла с обратным вызовом для чтения данных из него, или, если вы не используетене нужно выполнять какую-либо обработку, вы можете буквально установить обратный вызов READFUNCTION равным fp.read.

...