Python - Problème urllib

Résolu
Bonjour,

Je tente depuis quelques jours d'envoyer un fichier sur un mobile en usb (requete POST par serveur HTTP démarré par un autre programme ) par le biais de ce petit programme :

def sendFile(self, file_):
"""
to send a file
"""
url = "http://" + IP + "/" + file_
print "\n File sent to : " + file_
fileIn = open (PATH_LOC + '/' + file_, "r")
contenu = fileIn.read()
print "contenu:"
print contenu
#cont = urllib.urlencode({contenu : 0})
#print cont
try:
handle = urllib.urlopen (url, contenu)
print "contenu transfere: "
print handle.read()
except Exception:
import traceback
traceback.print_exc()
fileIn.close()
print "\n"
#end def sendFile

Le fichier d'arrivée est bien créé mais il est vide ... :/
Quelqu'un saurait-il ce qui ne va dans ce programme svp ? :)

Merci!
Bonne journée :)
Configuration: Windows XP
Firefox 3.0

17 réponses

  1. Modérateur
    Quand tu fais ton POST, je ne vois pas le nom du champ contenant le fichier.
    Dans un POST il doit être indiqué (tout comme tu le ferais dans un formulaire HTML).

    Voici un exempl de POST:
    https://sebsauvage.net/python/snyppets/index.html#http_post

    #!/usr/bin/python
    import urllib,urllib2
    
    url = 'http://www.commentcamarche.net/search/search.php3'
    parameters = {'Mot' : 'Gimp'}
    
    data = urllib.urlencode(parameters)    # Use urllib to encode the parameters
    request = urllib2.Request(url, data)
    response = urllib2.urlopen(request)    # This request is sent in HTTP POST
    page = response.read(200000)


    D'autre part, tu devrais ouvrir ton fichier en "rb" et non en "r".
    1. Modérateur
      GET /yop2.txt HTTP/1.1

      Ça, ça permet de récupérer le fichier yop2.txt fichier du serveur, pas d'en envoyer un vers le serveur.

      Pour envoyer un fichier vers le serveur, il faut bien faire un POST, mais pas avec le nom du fichier comme URL.
      Il faut le nom du programme sur le serveur qui va réceptionner la requête POST.
      1. Modérateur
        Il y a un exemple là: http://code.activestate.com/recipes/146306/

        Tu dois connaître:
        * le nom du programme sur le serveur web qui reçoit les fichiers
        * les paramètres qu'il accepte.

        Il semble même que quelqu'un ait pensé à faire une librairie juste pour faire de l'upload de fichiers avec urllib2:
        http://fabien.seisen.org/python/urllib2_multipart.html

        Dans son exemple:
        * le nom du programme sur le serveur qui reçoit les fichiers est script_upload.php
        * le nom du champ contenant le fichier est 'file'
        1. Merci ! :)

          Un autre problème se pose maintenant : urllib2.urlopen(url) est en 404 NOT FOUND, ce qui peut paraitre normal vu qu'il n'a pas créé le fichier, je n'ai pas trouvé de fonction qui créait le fichier préalablement pour éviter cette erreur.
          Y en a-t-il une ?

          Merci.
          1. Modérateur
            Normalement, l'URL ne soit pas être le nom du fichier, mais le nom du programme (sur le serveur web) qui va réceptionner et traiter le fichier.
            1. Dans ce cas là le fichier n'a pas vraiment à être traité (ça peut être un .txt, .rar, .jpg ... ) : en gros je ne vois pas quel type de programme pourrait gérer tout ça... Il y a un programme qui traite tout ? Ou c'est un programme qui doit gérer uniquement l'envoi et caler le fichier dans le bon dossier ?
              Merci.

              J'ai modifié mon programme de tout à l'heure en :

              def sendFile(self, file_):
                      url = "http://" + IP + "/" + file_
                      print "\n File sent to : " + file_
                      fileIn = open (PATH_LOC + '/' + file_, "rb")
                      contenu = fileIn.read()
                      try:
                          request = urllib2.Request( url , contenu)
                          handle = urllib2.urlopen( url )
                          print "contenu transfere: "
                          print handle.read()
                      except Exception:
                          import traceback
                          traceback.print_exc()
                      fileIn.close()
                      print "\n"
              1. Modérateur
                Où as-tu vu qu'il fallait lui envoyer un fichier de cette façon, dans la documentation du mobile ?
                1. Je n'ai pas de documentation du mobile. Je suis en stage où je dois m'occuper des transferts de fichiers en python vers les mobiles type iPhone.
                  1. Modérateur
                    Bon, sans documentation, c'est pas la peine. Tu ne peux pas taper à l'aveuglette en espérant faire mouche.

                    Il faut savoir comment envoyer ces fichiers.
                    Est-ce qu'il faut bien les envoyer sur un serveur HTTP ?
                    Si oui, sur quelle URL (http://ip/toto/titi.xxx) ?
                    En POST ou en GET ?
                    Avec quels paramètres de formulaire ?

                    Sans réponse à ces question, tu ne pourra pas le faire.
                    1. oui il faut envoyer sur un serveur HTTP, le fichier doit atterrir dans http://ip/lefichierenvoyé
                      jai un programme qui fait l'équivalent d'un GET qui fonctionne :

                          def getFile(self, file_):
                              """
                              to receive a file
                              """
                              url = "http://" + IP + "/"+ file_
                              print "\n File received : " + url
                              handle = urllib.urlopen (url)
                              contenu = handle.read()
                              print contenu
                              fileOut = open (PATH_LOC + '/'+ file_, "w")
                              fileOut.write (contenu)
                              fileOut.close()
                              print "\n"


                      Qu'appelles-tu paramètres exactement ? Ma classe File, qui contient ces deux méthodes, ne prend aucun paramètre; dans un premier temps j'avais mis le port et l'ip mais je ne m'en servais pas vraiment. (IP et PATH_LOC sont issus d'un fichier de config). J'ai jamais bossé avec des serveurs HTTP ou autres donc je ne sais pas du tout de quoi il a besoin.
                      1. Modérateur
                        jai un programme qui fait l'équivalent d'un GET qui fonctionne :

                        Quant tu le fais en GET, ça marche ?
                        Qu'est-ce que tu passe dans l'URL du GET ?
                        1. Exactement la même chose que pour le POST : http://ip/lefichierenquestion
                          Et ça fonctionne très bien.

                          [ Quand je fais le POST le serveur repère bien qu'un POST a été fait mais le fichier arrive quand même vide. ]
                          1. HTTP Server - A new client is connected
                            HTTP Server - Received request : GET /yop2.txt HTTP/1.1

                            Le serveur prend en paramètres l'ip du mobile et le port 80 en plus.
                            Il n'y a pas de '?' ou autre pris en compte.
                            1. Ok... mais c'est quel genre de programme qui peut faire ça ? ça ressemble à quoi ce qu'il faut mettre dans la requête ?
                              1. Ok merci pour ton aide. Je vais essayer ça.

                                Bonne journée ! :)
                                1. Finalement problème résolu : serveur HTTP qui n'attendait pas d'avoir les données pour faire le POST...

                                  Merci quand même j'ai appris pas mal de petits trucs grâce à tes liens !