2011-09-27 139 views
3

我需要建立从内容类型的PDF文件(与dexerity提出,如果该事项),从而使用户创建一个新文档和填充生成PDF的形式,随时可以下载后。所以基本上在创建/修改文档之后,应该创建PDF并将其存储在ZODB中(实际上我使用的是斑点),以便我可以将视图与“下载为PDF”链接起来。生成的Plone内容类型的PDF

我见过PDFNode,但它似乎没有什么我要找的。也有Produce & Publish,但它是一个web服务(?),我打算开发这个公司不希望(为了保密)在数据中心之外发送数据。

有什么想法?

回答

3

我实际上做这样的事情很多在我的一个项目上。我用Products.SmartPrintNG和fop虽然并没有做它的产品使用的标准方式(我认为它使用JavaScript来启动转换..怪异)。

两件事情:

  • 我不得不消毒的输出,因为FOP是相当敏感的
  • 使用LXML
  • 矿采用原型

不管怎么说,我的事件处理程序创建PDF最终看起来是这样的:

from Products.SmartPrintNG.browser import SmartPrintView 
from lxml.cssselect import CSSSelector 
from lxml.html import fromstring, tostring 
import re 

san_re = re.compile('(?P<width>width\=("|\')\d{1,5}(px|%|in|cm|mm|em|ex|pt|pc)?("|\'))') 

class Options(object): 

    def __init__(self, __dict): 
     self.__dict = __dict 

    def __getattr__(self, attr): 
     if self.__dict.has_key(attr): 
      return self.__dict[attr] 
     raise AttributeError(attr) 

def sanitize_xml(xml): 
    selector = CSSSelector('table,td,tr') 
    elems = selector(xml) 
    for el in elems: 
     if el.attrib.has_key('width'): 
      width = el.attrib['width'] 
      style = el.attrib.get('style', '').strip() 
      if style and not style.endswith(';'): 
       style += ';' 
      style += 'width:%s;' % width 
      del el.attrib['width'] 
      el.attrib['style'] = style 

    return xml 

def save_pdf(obj, event): 
    smartprint = SmartPrintView(obj, obj.REQUEST) 
    html = obj.restrictedTraverse('view')() 
    xml = fromstring(html) 
    selector = CSSSelector('div#content') 
    xml = selector(xml) 
    html = tostring(sanitize_xml(xml[0])) 
    res = smartprint.convert(
     html=html, 
     format='pdf2', 
     options=Options({'stylesheet': 'pdf_output_stylesheet', 'template': 'StandardTemplate'}) 
    ) 

    field = obj.getField('generatedPDF') 
    field.set(obj, res, mimetype='application/pdf', _initializing_=True) 
    field.setFilename(obj, obj.getId() + '.pdf') 
0

使用z3c.rml,工作得非常好,从一个RML模板产生的,而不是从HTML中可能会非常棘手转换PDF格式。

相关问题