Appengine - Reportlab(从模型中获取照片)

时间:2010-09-26 17:08:40

标签: python google-app-engine django-models reportlab

我正在使用Reportlab生成PDF。 无法从模型中检索照片。

#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))

当我创建生成PDF时,我收到了这个错误:

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'

如果我评论n.º419那条调用照片的行,一切都很顺利。 我已经在Datastore Viewer中进行了检查,模型还可以。

有人可以指出出了什么问题吗?

我应该使用%s代替str吗?但抛出相同的错误。

1 个答案:

答案 0 :(得分:12)

根据ReportLab API reference,drawImage()的参数是'image,x,y',而它看起来好像在传递'x,y,string'。

drawImage()的image参数需要文件名或ImageReader。

根据this post,ImageReader构造函数可以使用几种类型的参数。

<强>更新

在您发布的此代码中,您将ImageReader分配给'image',但将'imagem'(不存在)传递给drawImage:

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

另外,user.photo是什么类型的模型属性?

更新2:

您收到有关NoneType的错误 - 您确定user.photo是有效的blob,而不是None?

另外,blob is a subclass of str,但ImageReader需要StringIO - 所以我认为你需要将blob包装在StringIO中以将其传递给ImageReader,例如:

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

顺便说一下,我的猜测是ImageReader('http://www.reportlab.com/rsrc/encryption.gif')可能失败了,因为它可能正在尝试使用应用引擎不支持的API(即urlfetch从该服务器加载图像})。

更新3:

实际上它看起来像是ReportLab中的一个错误。

我下载了version 2.4 of ReportLab,并在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):

ImageReader构造函数调用_isPILImage以查看它是否传递了PIL图像。但是PIL在应用引擎上不可用,因此Image为None,因此引用Image.Image会抛出您所看到的in _isPILImage AttributeError: 'NoneType' object has no attribute 'Image'.

我还发现this blog post描述了如何将ReportLab与图像一起使用。有关如何解决此问题的详细信息,请参阅“PDF格式的图像”部分,以及使其在应用程序引擎上运行所需的其他修改。请注意,该博客文章中的行号似乎与我下载的2.4版本或错误消息中的行号不匹配 - 因此请搜索所提及的代码,而不是行号。

另请注意,没有PIL的ReportLab(即它将在​​app引擎上运行)只能绘制JPEG图像(如该博客文章中所述)。

最后,在此代码中您发布了:

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)

第一个问题是当你的标志应该是'image,x,y'时,你用'x,y,image'调用drawImage()。

其次,这里没有定义用户或p(也许你删除了那些代码?)。

第三,为什么get()有一个图像参数 - 你在创建webapp.WSGIApplication()时是否解析了一些URL?如果没有,则图像将为None,这就是为什么不会发生的原因。

更新4:

您现在获得的Imaging Library not available, unable to import bitmaps only jpegs错误是因为ReportLab无法读取jpeg以查找其宽度和高度。当你将它加载到blob中时,jpeg可能已损坏,或者jpeg可能是ReportLab不支持的格式。

在ReportLab的lib \ utils.py中,您可以暂时尝试更改以下内容(在2.5版的第578行附近):

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

就这样:

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

这将允许您查看readJPEGInfo()正在抛出的实际异常,这可能有助于找到问题的原因。

尝试帮助缩小问题范围的另一件事可能是将您为用户上传的file.jpg放入项目中,然后执行以下操作:

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

这将使用ImageReader直接从文件加载jpeg,而不是从blob加载。

如果这样可行,则问题是您的blob无效,因此您应该查看图片上传代码。如果失败,则jpeg本身无效(或ReportLab不支持)。

更新5:

你正在使用它:

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

根据此页面上的documentation on resize,它采用output_encoding参数,默认为PNG。所以试试这个:

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