Appengine – Reportlab (Obtener foto del modelo)

Estoy usando Reportlab para generar un PDF. No se puede recuperar una foto de un modelo.

#Personal Info p.drawImage('myPhoto.jpg', 40, 730) p.drawString(50, 670, 'Your name:' + '%s' % user.name) p.drawImage (50, 640, 'Photo: %s' % (user.photo)) 

Cuando creo en generar PDF, recibí este error:

 Traceback (most recent call last): File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 513, in __call__ handler.post(*groups) File "C:\Users\hp\workspace\myApp\src\main.py", line 419, in post p.drawImage (50, 640, 'Photo: %s' % (user.photo)) File "reportlab.zip\reportlab\pdfgen\canvas.py", line 825, in drawImage File "reportlab.zip\reportlab\pdfbase\pdfdoc.py", line 2076, in __init__ File "C:\Python25\lib\ntpath.py", line 189, in splitext i = p.rfind('.') AttributeError: 'int' object has no attribute 'rfind' 

Si comento la línea que n.º 419, que llama a la foto, todo va bien. Ya lo he inspeccionado en Datastore Viewer y los modelos están bien.

¿Alguien puede señalar qué está mal?

¿Debo usar% s en lugar de str? Pero arroja el mismo error.

De acuerdo con la referencia de la API ReportLab , drawImage () tiene los argumentos ‘imagen, x, y’, mientras que parece que estás pasando ‘x, y, cadena’.

El argumento de la imagen para drawImage () requiere un nombre de archivo o ImageReader.

De acuerdo con esta publicación , el constructor ImageReader puede tomar varios tipos de argumentos.

Actualizar:

En este código que publicaste, asignas ImageReader a ‘image’, pero pasas ‘imagem’ (que no existe) a drawImage:

 image = ImageReader(user.photo) p.drawImage(imagem) 

Además, ¿qué tipo de propiedad modelo es user.photo?

Actualización 2:

Recibirá un error sobre NoneType: ¿está seguro de que user.photo es un blob válido y no None?

Además, un blob es una subclase de str , pero ImageReader requiere un StringIO , por lo que creo que necesitas envolver el blob en un StringIO para pasarlo a ImageReader, por ejemplo:

 import StringIO image = ImageReader(StringIO.StringIO(user.photo)) p.drawImage(image) 

Por cierto, mi conjetura es que ImageReader('http://sofes.miximages.com/python/encryption.gif') puede haber fallado porque puede estar intentando cargar la imagen de ese servidor, utilizando una API que utiliza el motor de la aplicación. no soporta (es decir, no urlfetch ).

Actualización 3:

En realidad, parece que es un error en ReportLab.

Descargué la versión 2.4 de ReportLab y encontré esto en utils.py:

 def _isPILImage(im): try: return isinstance(im,Image.Image) except ImportError: return 0 class ImageReader(object): "Wraps up either PIL or Java to get data from bitmaps" _cache={} def __init__(self, fileName): ... if _isPILImage(fileName): 

El constructor de ImageReader llama a _isPILImage para ver si se pasó una imagen PIL. Sin embargo, PIL no está disponible en el motor de la aplicación, por lo que la Imagen es Ninguna, y por lo tanto, al hacer referencia a la Imagen.Imagen arroja el in _isPILImage AttributeError: 'NoneType' object has no attribute 'Image'. que estas viendo

También encontré esta publicación de blog que describe cómo usar ReportLab con imágenes. Consulte la sección ‘Imágenes en PDF’ para obtener detalles sobre cómo solucionar este problema, así como otra modificación que se requiere para que funcione en el motor de aplicaciones. Tenga en cuenta que los números de línea en esa publicación del blog no parecen coincidir con la versión 2.4 que descargué, o los números de línea en sus mensajes de error, así que busque el código mencionado, en lugar de los números de línea.

También tenga en cuenta que ReportLab sin PIL (es decir, como se ejecutará en el motor de la aplicación) solo puede dibujar imágenes JPEG (como también se menciona en esa publicación del blog).

Finalmente, en este código usted publicó:

 def get(self, image): if image is not None: image = ImageReader(StringIO.StringIO(user.photo)) p.drawImage(40, 700, image) p.setLineWidth(.3) p.setFont('Helvetica', 10) p.line(50, 660, 560, 660) 

El primer problema es que estás llamando a drawImage () con ‘x, y, image’, cuando los argumentos deben ser ‘image, x, y’.

En segundo lugar, ni el usuario ni p están definidos aquí (¿tal vez recortó ese código?).

En tercer lugar, ¿por qué hay un argumento de imagen para obtener ()? ¿Analiza algo fuera de la URL cuando crea la aplicación web.WSGIApplication ()? Si no, la imagen será Ninguna, por lo que no pasará nada.

Actualización 4:

La Imaging Library not available, unable to import bitmaps only jpegs error Imaging Library not available, unable to import bitmaps only jpegs que está obteniendo ahora porque ReportLab no puede leer el jpeg para encontrar su ancho y alto. Tal vez el jpeg se dañó cuando lo cargó en el blob, o tal vez el jpeg está en un formato que ReportLab no admite.

En lib \ utils.py de ReportLab, puede intentar cambiar temporalmente lo siguiente (alrededor de la línea 578 de la versión 2.5):

 try: self._width,self._height,c=readJPEGInfo(self.fp) except: raise RuntimeError('Imaging Library not available, unable to import bitmaps only jpegs') 

Sólo para esto:

 self._width,self._height,c=readJPEGInfo(self.fp) 

Esto le permitirá ver la excepción real que readJPEGInfo() está lanzando, lo que podría ayudar a encontrar la causa del problema.

Otra cosa para tratar de ayudar a reducir el problema podría ser colocar el archivo.jpg que cargó para el usuario en su proyecto, luego hacer algo como esto:

 imagem = canvas.ImageReader(StringIO.StringIO(open('file.jpg', 'rb').read())) 

Esto cargará el jpeg directamente desde el archivo, usando ImageReader, en lugar de hacerlo desde el blob.

Si esto funciona, entonces el problema es que su blob no es válido, por lo que debe mirar el código de carga de su imagen. Si falla, entonces el archivo jpeg no es válido (o no es compatible con ReportLab).

Actualización 5:

Estás usando esto:

 photo = images.resize(self.request.get('photo'), 32, 32) 

De acuerdo con la documentación sobre el cambio de tamaño en esta página, toma un argumento de output_encoding que por defecto es PNG. Así que intente esto en su lugar:

 photo = images.resize(self.request.get('photo'), 32, 32, images.JPEG)