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

Mar*_*ho 5 python google-app-engine reportlab django-models

我使用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))
Run Code Online (Sandbox Code Playgroud)

当我创建生成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'
Run Code Online (Sandbox Code Playgroud)

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

有人能指出出错了吗?

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

Sax*_*uce 12

根据ReportLab API参考,drawImage()具有参数'image,x,y',而它看起来好像在传递'x,y,string'.

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

根据这篇文章,ImageReader构造函数可以采用几种类型的参数.

更新:

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

image = ImageReader(user.photo) 
p.drawImage(imagem)
Run Code Online (Sandbox Code Playgroud)

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

更新2:

你收到一个关于NoneType的错误 - 你确定user.photo是一个有效的blob,而不是None吗?

另外,blob是str的子类,但是ImageReader需要一个StringIO - 所以我认为你需要将一个blob包装在一个StringIO中以将它传递给ImageReader,例如:

import StringIO
image = ImageReader(StringIO.StringIO(user.photo))
p.drawImage(image)
Run Code Online (Sandbox Code Playgroud)

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

更新3:

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

我下载了ReportLab的2.4版本,并在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):
Run Code Online (Sandbox Code Playgroud)

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

我还发现了这篇博文,其中介绍了如何将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)
Run Code Online (Sandbox Code Playgroud)

第一个问题是,当argments应该是'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')
Run Code Online (Sandbox Code Playgroud)

为此:

self._width,self._height,c=readJPEGInfo(self.fp)
Run Code Online (Sandbox Code Playgroud)

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

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

imagem = canvas.ImageReader(StringIO.StringIO(open('file.jpg', 'rb').read()))
Run Code Online (Sandbox Code Playgroud)

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

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

更新5:

你正在使用这个:

photo = images.resize(self.request.get('photo'), 32, 32)
Run Code Online (Sandbox Code Playgroud)

根据此页面上有关调整大小文档,它采用output_encoding参数,默认为PNG.所以试试这个:

photo = images.resize(self.request.get('photo'), 32, 32, images.JPEG)
Run Code Online (Sandbox Code Playgroud)