2010-11-05 17 views
5

Je souhaite créer un service sur Google App Engine (Python) qui recevra l'URL d'une image et la stockera sur Google Storage. J'ai réussi à télécharger à partir d'un fichier local en utilisant boto ou gsutil ligne de commande, mais pas en récupérant le fichier via l'URL. J'ai essayé de le faire en utilisant le HTTP requests (PUT) et j'obtiens des réponses d'erreur pour les mauvaises signatures. Évidemment, je fais quelque chose de mal, mais malheureusement, je ne sais pas où. Donc, ma question est: Comment puis-je récupérer un fichier à partir d'une URL et le stocker sur Google Storage en utilisant Python pour Google App Angine?Comment enregistrer un fichier sur Google Storage à partir d'une URL sur Google App Engine?

Voici ce que je l'ai fait (en utilisant un autre answer):

class ImportPhoto(webapp.RequestHandler): 
    def get(self): 
     self.response.headers['Content-Type'] = 'text/plain' 
     srow = self.response.out.write 
     url = self.request.get('url') 
     srow('URL: %s\n' % (url)) 
     image_response = urlfetch.fetch(url) 
     m = md5.md5() 
     m.update(image_response.content) 
     hash = m.hexdigest() 
     time = "%s" % datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") 
     str_to_sig = "PUT\n" + hash + "\n\n" + 
         time + "\nx-goog-acl:public-read\n/lipis/8418.png" 
     sig = base64.b64encode(hmac.new(
            config_credentials.GS_SECRET_ACCESS_KEY, 
            str_to_sig, hashlib.sha1).digest()) 
     total = len(image_response.content) 
     srow('Size: %d bytes\n' % (total)) 

     header = {"Date": time, 
        "x-goog-acl": "public-read", 
        "Content-MD5": hash, 
        'Content-Length': total, 
        'Authorization': "GOOG1 %s:%s" % 
            (config_credentials.GS_ACCESS_KEY_ID, sig)} 

     conn = httplib.HTTPConnection("lipis.commondatastorage.googleapis.com") 
     conn.set_debuglevel(2) 

     conn.putrequest('PUT', "/8418.png") 
     for h in header: 
      conn.putheader(h, header[h]) 
     conn.endheaders() 
     conn.send(image_response.content + '\r\n') 
     res = conn.getresponse() 

     srow('\n\n%d: %s\n' % (res.status, res.reason)) 
     data = res.read() 
     srow(data) 
     conn.close() 

Et je reçois comme réponse:

URL: https://stackoverflow.com/users/flair/8418.png 
Size: 9605 bytes 

400: Bad Request 
<?xml version='1.0' encoding='UTF-8'?><Error><Code>BadDigest</Code><Message>The Content-MD5 you specified did not match what we received.</Message><Details>lipis/hello.jpg</Details></Error> 
+0

Pouvez-vous poster du code que le POU et le serveur répondent? –

+0

@Peter Knego J'ai mis à jour ma réponse. – Lipis

Répondre

1

Avez-vous lu les documents sur how to sign requests? La chaîne à signer doit inclure les en-têtes Content-MD5, Content-Type et Date, en plus des en-têtes personnalisés et du chemin d'accès aux ressources.

+0

Je l'ai fait mais je ne peux pas le faire fonctionner. Pouvez-vous me donner un exemple que je pourrais essayer? – Lipis

+0

Vous n'incluez pas ces en-têtes dans la chaîne que vous signez dans l'exemple de code que vous avez donné. Essayez de les ajouter comme documenté, et si cela ne fonctionne toujours pas, montrez-nous le code que vous utilisez alors. –

+0

Merci .. après avoir à nouveau lu le manuel, il a travaillé: D – Lipis

1

Content-MD5 l'en-tête est facultatif pour PUT requests. Essayez de laisser cela pour un test. Les en-têtes requis sont également Authorization, Date et Host. Il semble que votre requête manque Host header.

+0

Lorsque j'ai ajouté l'hôte, je recevais toujours la même erreur. Lorsque j'ai supprimé Content-MD5, je reçois un * 403: Interdit * _La signature de la requête que nous avons calculée ne correspond pas à la signature que vous avez fournie. Vérifiez votre clé secrète Google et la méthode de signature. _ – Lipis

+0

Essayez d'utiliser des plugins Chrome Potster ou Firefox Poster pour créer manuellement des requêtes PUT. Vérifiez avec divers en-têtes jusqu'à ce que vous ayez raison. Ensuite, transférez ceci au code. https://chrome.google.com/extensions/detail/cdjfedloinmbppobahmonnjigpmlajcd?hl=fr https://addons.mozilla.org/en-US/firefox/addon/2691/ –

+0

ne peut pas le faire fonctionner. Je pense que ma signature est fausse donc je ne peux pas obtenir ce droit de le mettre sur Poster :(Dois-je faire sens dans le code ci-dessus sur la façon de le calculer? – Lipis