2010-11-05 20 views
5

Quiero crear un servicio en Google App Engine (Python) que recibirá una URL de una imagen y la almacenará en Google Storage. Logré cargar desde un archivo local usando boto o gsutil línea de comandos, pero no al recuperar el archivo a través de la URL. Intenté hacerlo usando el HTTP requests (PUT) y obtuve respuestas de error para las firmas incorrectas. Obviamente estoy haciendo algo mal, pero desafortunadamente no tengo idea de dónde.¿Cómo se puede almacenar un archivo en Google Storage desde la URL en Google App Engine?

Así que mi pregunta es: ¿cómo puedo recuperar un archivo de una URL y almacenarlo en Google Storage usando Python para Google App Angine?

Esto es lo que he hecho (utilizando otro 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() 

Y yo estoy como una respuesta:

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

¿Puedes publicar algún código que haga la POU y la respuesta del servidor? –

+0

@Peter Knego Actualicé mi respuesta. – Lipis

Respuesta

1

¿Ha leído la documentación sobre how to sign requests? La cadena para firmar debe incluir los encabezados Content-MD5, Content-Type y Date, además de los encabezados personalizados y la ruta del recurso.

+0

Lo hice pero no puedo hacerlo funcionar. ¿Me puedes dar un ejemplo que pueda probar? – Lipis

+0

No estás incluyendo esos encabezados en la cadena que firmas en el código de ejemplo que diste. Intente agregarlos según lo documentado, y si aún no funciona, muéstrenos el código que está utilizando en ese momento. –

+0

Gracias ... después de volver a leer el manual, funcionó: D – Lipis

1

Content-MD5 encabezado es opcional para PUT requests. Trata de dejar esto para una prueba.

Además, los encabezados obligatorios son Authorization, Date y Host. Parece que su solicitud no está en el encabezado Host.

+0

Cuando agregué el host todavía recibía el mismo error. Cuando eliminé Content-MD5, recibo un * 403: Prohibido * _La firma de solicitud que calculamos no coincide con la firma que proporcionó. Verifique su clave secreta de Google y el método de firma. – Lipis

+0

Pruebe usar los complementos de Chrome Potster o Firefox Poster para crear manualmente las solicitudes PUT. Verifica con varios encabezados hasta que lo hagas bien. Luego transfiere esto al código. https://chrome.google.com/extensions/detail/cdjfedloinmbppobahmonnjigpmlajcd?hl=es https://addons.mozilla.org/en-US/firefox/addon/2691/ –

+0

no puede hacer que funcione. Creo que mi firma es incorrecta, así que no puedo obtener ese derecho para ponerla en el cartel :(¿Tengo algún sentido en el código anterior sobre cómo calcularlo? – Lipis