2011-09-27 140 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格式。

相關問題