在AppEngine Python上使用Reportlab生成的PDF文档中添加图像文件的正确方法

时间:2012-02-29 19:05:55

标签: python image google-app-engine reportlab

我正在尝试使用App Engine Python上的reportlab生成PDF报告。

但我不知道如何正确附加图像。

图像是静态的。

这是我项目的目录树。

enter image description here

这就是我所做的(在 chipas.py '内)来获取图像:

im = Image('../static/logo.png',1*inch, 1*inch)
story.append(im)
...

我得到的堆栈跟踪:

  

Traceback(最近一次调用最后一次):文件   “C:\用户\卢卡斯\收存箱\ DESARROLLO \的Python \ Windows \应用服务引擎\谷歌\应用服务引擎\分机\ webapp_webapp25.py”,   第701行,在电话中       handler.get(* groups)文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ chipas.py”,   第1035行,在得到       doc.build(story)文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ _ reportlab \ platypus \ doctemplate.py”,   1117行,正在构建中       BaseDocTemplate.build(self,flowables,canvasmaker = canvasmaker)文件   “C:\用户\卢卡斯\收存箱\ DESARROLLO \工作空间\蟒\ chipas窗口\ SRC \ ReportLab的\鸭嘴兽\ doctemplate.py”,   第880行,正在构建中       self.handle_flowable(flowables)文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ _ reportlab \ platypus \ doctemplate.py”,   第763行,在handle_flowable中       if frame.add(f,canv,trySplit = self.allowSplitting):文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ reportlab \ platypus \ frames.py”,   第159行,在_add       w,h = flowable.wrap(aW,h)文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ _ reportlab \ platypus \ flowables.py”,   第408行,包裹       return self.drawWidth,self.drawHeight File“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ _ reportlab \ platypus \ flowables.py”,   第402行,在 getattr 中       self._setup_inner()文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ _ reportlab \ platypus \ flowables.py”,   第368行,在_setup_inner中       img = self._img文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ _ reportlab \ platypus \ flowables.py”,   第398行, getattr       self._img = ImageReader(self._file)文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ reportlab \ lib \ utils.py”,   第541行, init       if _isPILImage(fileName):文件“C:\ Users \ Lucas \ Dropbox \ Desarrollo \ workspace \ python \ chipas-windows \ src \ reportlab \ lib \ utils.py”,   第521行,在_isPILImage中       return isinstance(im,Image.Image)AttributeError:'NoneType'对象没有属性'Image'INFO 2012-02-29 19:54:37,276   dev_appserver.py:4247]“GET   / PDF?pedido = ahVkZXZ-Y2hpcGFzLWludGhlY2xvdWRyLwsSBlBlZGlkbyIjMjAxMi0wMi0yOSAxOTo1NDoxOHRlc3RAZXhhbXBsZS5jb20M   HTTP / 1.1“500 -

在使用reportlab生成的pdf文档中添加图像文件的正确方法是什么? 非常感谢提前!

4 个答案:

答案 0 :(得分:6)

ReportLab要求PIL用于JPEG以外的图像(PIL在Appengine制作时不可用),但它本身支持JPEG(请参阅下面的注释)。因此,在渲染PDF文件时,您需要为ReportLab提供JPEG图像。使用用户提交的图像,我首先使用Appengine的API在渲染之前将图像转换为JPEG。

所以第1步是将徽标从png更改为jpeg。

其次,Appengine不允许您从静态目录中读取文件。如果您尝试,它会出现“文件无法访问”错误。将.jpg切换到/ static /以外的目录。

因此,无论您使用哪种方法来定义文件的相对路径(gfortune的代码都可以完美地工作),要渲染图像,只需使用:

f = open(path_to_file,'rb')

story.append(图片(f))

注意:几年前,ReportLab有一个错误,它仍会尝试访问PIL,即使对于JPEG文件也是如此。我与开发人员通信,他们提供了绕过PIL for JPEG文件的版本。我不确定哪个版本是当前版本,所以请记住这一点。

答案 1 :(得分:3)

主要解决方案

看起来这篇文章的原始错误是由于PIL可能没有被安装,或者可能是旧版PIL中的错误。有关类似情况,请参阅http://www.openerp.com/forum/topic18147.html。尝试安装最新版本的PIL。

另外,请在接受的解决方案和评论的末尾看Appengine - Reportlab (Get Photo from Model)

发布的代码中的另一个潜在问题

虽然这可能与提出的问题没有直接关系,但您确定im正确加载了吗?请记住,您设置的路径是相对于启动应用程序的目录而不是相对于当前文件的目录。使用__file__和一些os.path技巧来设置相对于chipas.py的路径,假设问题是正确的。如果它不是您现在正在处理的问题,那么您很快就会遇到这个问题。

要引用相对于当前文件目录的路径,可以使用以下内容:

代码

import os.path

def path_relative_to_file(base_file_path, relative_path):
    base_dir = os.path.dirname(os.path.abspath(base_file_path))
    return os.path.normpath(os.path.join(base_dir, relative_path))



print(__file__)
print(path_relative_to_file(__file__, '../static/logo.png'))


#Breaks if this code is run from a different directory
print(os.path.abspath('../static/logo.png'))

输出

gfortune@gfortune:/var/log$ python /home/gfortune/temp/temp.py
/home/gfortune/temp/temp.py
/home/gfortune/static/logo.png
/var/static/logo.png

请注意' ../ static'的路径即使我从/ var / log启动了程序也能正常工作。另请注意,如果从/ var / log运行它,盲目地使用../static和abspath会中断。

您可以通过从相关模块传递__file__来使用该函数作为一个小帮助函数,或者您可以直接在chipas.py

中使用它的逻辑

答案 2 :(得分:3)

有两种方法可以做到。

如果您只是使用画布:

canvas.drawInlineImage(APP_ROOT + "/static/footer_image.png", inch*.25, inch*.25, PAGE_WIDTH-(.5*inch), (.316*inch))

如果你使用platypus和flowables

(答案取自:http://www.tylerlesmann.com/2009/jan/28/writing-pdfs-python-adding-images/

import os
import urllib2
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Image

filename = './python-logo.png'

def get_python_image():
    """ Get a python logo image for this example """
    if not os.path.exists(filename) :
        response = urllib2.urlopen('http://www.python.org/community/logos/python-logo.png')
        f = open(filename, 'w')
        f.write(response.read())
        f.close()

get_python_image()

doc = SimpleDocTemplate("image.pdf", pagesize=letter)
parts = []
parts.append(Image(filename))
doc.build(parts)

答案 3 :(得分:0)

尝试这个简单的功能: 这为我工作....

def PrintImage(request):
    response = HttpResponse(content_type='application/pdf')
    doc = SimpleDocTemplate(response,topMargin=2)

    doc.pagesize = landscape(A6)
    elements = []
    I = Image('http://demoschoolzen.educationzen.com/images/tia.png')
    I.drawHeight =  0.7*inch
    I.drawWidth = 0.7*inch
    elements.append(I)
    doc.build(elements) 
    return response

并从您的网址中调用