使用reportlabs在金字塔中将临时图像写入temp pdf

时间:2014-05-01 18:11:13

标签: python pdf pdf-generation pyramid reportlab

我正在使用python 3,使用金字塔和reportlabs来生成动态pdf。

我在将图像写入pdf时遇到问题。我在Web中使用Reportlab来生成带有图像的pdf,我的图像不是存储在本地,而是在远程服务器上。我将它们本地下载到临时目录中(它们正在保存,我已经检查过)当我将图像添加到pdf时,它们的空间正在分配,但图像没有显示。

这是我的相关代码(简化):

      # creates pdf in memory
      doc = SimpleDocTemplate(pdfName, pagesize=A4)

      elements = []

      for item in model['items']:
        # image goes here:
        if item['IMAGENAME']:
          response = getImageFromRemoteServer(item['IMAGENAME'])
          dir_filename = directory + item['IMAGENAME']
          if response.status_code == 200:
          with open(dir_filename, 'wb') as f:
            for chunk in response.iter_content():
              f.write(chunk)

        questions.append(Image(dir_filename, width=2*inch, height=2*inch))

      # create and save the pdf
      doc.build(elements,canvasmaker=NumberedCanvas)

我已按照此处的用户指南https://www.reportlab.com/docs/reportlab-userguide.pdf进行了尝试,并尝试了上述方式,以及嵌入式图像(如用户指南在段落部分中所述)并将图像放入表格中。

我也看了here:它对我没有帮助。

我的问题是,什么是下载图像并放入pdf的权利?

编辑:固定代码缩进

编辑2:

回答说,我终于要在PDF中获取图像了。我不确定是什么触发器才能让它发挥作用。知道我改变的唯一的事情是现在我使用urllib来做请求而在我没有之前。这是我的工作代码(仅针对问题进行了简化,这更加抽象并封装在我的代码中。):

doc = SimpleDocTemplate(pdfName, pagesize=A4)
# array of elements in the pdf
elements = []
for question in model['questions']:
  # image goes here:
  if question['IMAGEFILE']:
    filename = question['IMAGEFILE']
    dir_filename = directory + filename
    url = get_url(settings, filename)
    response = urllib.request.urlopen(url)
    raw_data = response.read()      

    f = open(dir_filename, 'wb')
    f.write(raw_data)
    f.close()

    response.close()
    myImage = Image(dir_filename)
    myImage.drawHeight = 2* inch
    myImage.drawWidth = 2* inch
    myImage.hAlign = "LEFT"
    elements.append(myImage)

# create and save the pdf
doc.build(elements)

2 个答案:

答案 0 :(得分:0)

使代码独立于文件的来源。从文档生成中分离文件/资源​​检索。确保您的工具集正在使用本地文件。封装代码以加载加载器类或函数中的文件。封装是重要的。本周在查看thumbor加载程序类时再次注意到这一点。 如果有效,你知道reportlab,PIL和你的应用程序基本上是可行的。

然后使用http://path/to/remote/files之类的URI使您的代码使用远程文件。

之后,您可以根据环境或用例切换使用文件加载器或httploader。

另一个选择是使用file://path/to/file

之类的URI使您的代码使用本地文件

这样,从本地切换到远程时唯一的变化就是URL。可能你需要一个支持这个的python库。 requests库非常适合下载内容,很可能它也支持URL方案file://

答案 1 :(得分:0)

很可能lazy参数负责您的第一个代码示例未呈现图像。触发reportlab在临时文件的上下文管理器之外的PDF呈现可能会导致这种行为。

reportlab.platypus.flowables.py(使用版本3.1.8)

class Image(Flowable):
    """an image (digital picture).  Formats supported by PIL/Java 1.4 (the Python/Java Imaging Library
       are supported.  At the present time images as flowables are always centered horozontally
       in the frame. We allow for two kinds of lazyness to allow for many images in a document
       which could lead to file handle starvation.
       lazy=1 don't open image until required.
       lazy=2 open image when required then shut it.
    """
    _fixedWidth = 1
    _fixedHeight = 1
    def __init__(self, filename, width=None, height=None, kind='direct', mask="auto", lazy=1):
    """If size to draw at not specified, get it from the image."""
    self.hAlign = 'CENTER'
    self._mask = mask
    fp = hasattr(filename,'read')
    if fp:
        self._file = filename
        self.filename = repr(filename)
        ...

代码示例的最后三行告诉您可以传递具有read方法的对象。这正是对urllib.request.urlopen(url)的调用返回的原因。使用该内存缓冲区可以创建Image实例。无需对文件系统具有写入权限,无需在PDF呈现后删除这些文件。应用我们的新知识来提高代码可读性。由于您的用例包括使用支持python文件API的内存缓冲区检索远程资源,因此组装PDF文件的方法可能更为简洁。

from contextlib import closing
import urllib.request

doc = SimpleDocTemplate(pdfName, pagesize=A4)
# array of elements in the pdf
elements = []
for question in model['questions']:
  # download image and create Image from file-like object
  if question['IMAGEFILE']:
    filename = question['IMAGEFILE']
    image_url = get_url(settings, filename)

    with closing(urllib.request.urlopen(image_url)) as image_file:
      myImage = Image(image_file, width=2*inch, height=2*inch)
      myImage.hAlign = "LEFT"
      elements.append(myImage)

# create and save the pdf
doc.build(elements)

参考