2010-05-19 3 views
1

Je tente de télécharger un fichier comme celui-ci:fichier objet à partir Uploading fichier avec 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() 

Cela fonctionne très bien. Cependant, cela ne fonctionne que si le fichier est local. Si je devais aller chercher l'image telle que:

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

Comment pourrais-je passer resp.fp comme un objet de fichier au lieu de l'écrire dans un fichier et passer le nom de fichier? Est-ce possible?

Répondre

4

Il pourrait être possible dans des situations parfaites pour se connecter essentiellement les deux cours d'eau, mais ce ne serait pas une solution très robuste. Il y a un tas de conditions aux limites laid:

  • La prise de réponse peut-être encore réception de données, et/ou être au point mort, causant ainsi vous d'affamer et briser le POST (parce que pycurl n'est pas attendre devoir attendre les données au-delà de la fin actuelle du "fichier" ).
  • La réponse peut réinitialiser, et vous n'avez pas le dossier complet, mais vous avez déjà posté un tas de données - ce qu'il faut faire dans ce cas?
  • Le fichier que vous aller chercher avec urllib pourrait être chunked-encodées, de sorte que vous devez effectuer certaines opérations sur les en-têtes MIME pour réassemblage - vous ne pouvez pas aveuglément les données transmettre.
  • Vous ne savez pas nécessairement la taille du fichier que vous obtenez est, il est donc difficile de fournir la bonne longueur de contenu sur le POST, alors vous devez écrire chunked.
  • probablement un tas d'autres problèmes que je ne peux pas penser à du haut de ma tête ...

Vous serez beaucoup mieux d'écrire le fichier sur le disque temporairement, puis une fois que vous savez POSTer vous avez tout. Si vous vouliez faire cela, le meilleur moyen serait probablement d'implémenter votre propre objet semblable à un fichier qui gèrerait le pont entre les deux connexions (pourrait correctement mettre en mémoire tampon, gérer le décodage, etc.).

EDIT:

Basé sur le commentaire que vous avez laissé - absolument - vous avez juste besoin de setopt READFUNCTION. Consultez l'exemple de file_upload à:

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

Il fait exactement cela en faisant une enveloppe minuscule sur un objet de fichier avec un rappel pour lire les données de celui-ci, ou bien si vous n'avez pas besoin de faire tout traitement, vous pouvez définir le rappel READFUNCTION comme étant fp.read.

+0

Ce fut sans doute pas le meilleur exemple parce que ce n'est pas exactement ce que je faisais des choses. Mon point était que le contenu du fichier est déjà disponible via un objet fichier, donc je voulais savoir s'il y avait un moyen alternatif de passer ce handle de fichier à PyCurl au lieu de passer un nom de fichier. – Tom

+0

@Tom: Voir ma réponse éditée - ce que vous essayez de faire est réellement très trivial si vous avez déjà un objet de fichier qui est par ailleurs robuste. –

Questions connexes