• html2pdf

Document Actions
Réponses: 42   Visites: 0
Up one level
Vous devez être un membre enregistré pour contribuer sur ce forum. Inscrivez-vous maintenant

 • html2pdf

Posté par fcarlier le 26/01/2005 11:21
Bonjour,

Je relance le sujet sur html2pdf !!

Je viens de detecter 2 problemes :

* Quand on a un site en utf-8, la génération du pdf n'est pas belle !!!
htmldoc possede un champ --charset mais n'accepte pas le utf-8
une solution intermédiaire ??

* Il ne veut pas générer de pdf des PloneArticle car il dit ne pas recevoir de html !!

A votre bon coeur !!!
  •  • html2pdf

    Posté par fcarlier le 26/01/2005 11:47
    Oups je me repond à moi même pour la premiere question !! :

    faire un script utf2iso avec :
    code:
    errors="strict" 
    charset="utf-8" 

    return unicode(chaineUTF, charset, errors).encode("iso-8859-1", errors)


    et dans le viewPdf : remplace
    "structure python:here.CookedBody(stx_level=2)"
    par
    "structure python:here.utf2iso(here.CookedBody(stx_level=2))"

    Cela régle le probleme !!!

    Peut etre faudrait il completer le HowTo !!! avec un utf2iso plus élaborer !
  •  • html2pdf

    Posté par macadames le 26/01/2005 19:18
    > Peut etre faudrait il completer le HowTo !!! avec un utf2iso plus élaborer !

    C clair que tout ça a été fait à l'impulsion et faudrait tout réécrire proprement, faut voir avec dam's qui a pas mal de billes sur le sujet je crois.

    Autres questions avec html2pdf :

    J'ai trouvé que l'install sous Linux n'est pas évidente car pour avoir le composant gratuit g pas mal chercher et g du compiler.

    Pour obtenir le contenu html d'un ploneArticle c pas la meme syntaxe que pour un document plone standard, il suffit de regarder dans le template ploneArticleview.pt ou autre syntaxe avoisinante.

    Ce qui serait vraiment cool c'est d'avoir doc2pdf xls2pdf et j'en passe ...

    :cool:
  •  • html2pdf

    Posté par vegalien le 26/01/2005 20:32
    une remarque :

    htmldoc travaille au niveau linux et recupere donc le contenu en tant qu'anonyme, à moins de passer explicitement userid:passwd dans l'URL. :shocked:

    en conséquence, la manip évoquée ne peut pas fonctionner avec des document sur lesquels anonye n'a pas le droit de lecture. :cry:
  •  • html2pdf

    Posté par fcarlier le 27/01/2005 09:08
    > J'ai trouvé que l'install sous Linux n'est pas évidente car pour avoir le composant gratuit g pas mal chercher et g du compiler.

    Sous Linux Debian : APT-GET INSTALL HTMLDOC
    On peut pas faire plus simple !!
    :grin:

    Sinon, je regarde de ce pas le ploneArticle_view.pt !!! je n'y avais pas penser !!! plus qu'a adapter le script pour faire test entre Plone ou autre doc !!
  •  • html2pdf

    Posté par fcarlier le 27/01/2005 09:35
    Original Message -[01/27/2005]
    Original Message -[01/27/2005]
    Bon,
    Si je remplace le code, dans viewPdf :

    code:
      <div class="stx" tal:condition="len_text" tal:attributes="class python:test(here.text_format== 'structured-text', 'stx', 'plain')"> 
        <div tal:replace="structure python:here.utf2iso(here.CookedBody(stx_level=2))" />   
      </div>


    par :

    code:
      <div class="stx" tal:condition="len_text"> 
        <div tal:replace="structure python:here.utf2iso(here.CookedBody())" />   
      </div>


    Cela marche aussi pour PloneArticle

    Me reste plus qu'a comprendre l'interet de l'attibut class + stx_level=2, pour pouvoir réaliser l'équivalent pour mon PloneArticle
    Bon,
    Si je remplace le code, dans viewPdf :

    code:
      div class="stx" tal:condition="len_text" tal:attributes="class python:test(here.text_format== 'structured-text', 'stx', 'plain')"
        div tal:replace="structure python:here.utf2iso(here.CookedBody(stx_level=2))" /
      /div


    par :

    code:
      div class="stx" tal:condition="len_text"
        div tal:replace="structure python:here.utf2iso(here.CookedBody())" /
      /div


    Cela marche aussi pour PloneArticle

    Me reste plus qu'a comprendre l'interet de l'attibut class + stx_level=2, pour pouvoir réaliser l'équivalent pour mon PloneArticle
    Bon,
    Si je remplace le code, dans viewPdf :

    code:
        {div tal:replace="structure python:here.utf2iso(here.CookedBody(stx_level=2))" /}


    par :

    code:
        {div tal:replace="structure python:here.utf2iso(here.CookedBody())" /}


    Cela marche aussi pour PloneArticle

    Me reste plus qu'a comprendre l'interet de stx_level=2, pour pouvoir réaliser l'équivalent pour mon PloneArticle
  •  • html2pdf

    Posté par fcarlier le 27/01/2005 09:47
    Bon, en ajoutant un tal:condition ?§

    Je me souviens plus de la ligne par faire si objet="PloneArticle" !!

    comme cela on peut mettre dans le viewPdf, soit le fichier classique, soit l'appel vers getModel() !!
  •  • html2pdf

    Posté par fcarlier le 02/02/2005 11:01
    toujours pas trouvé !!! la ligne ZPT pour tester l'objet courant est savoir si c'est un PloneArticle !!

    help me please !
  •  • html2pdf

    Posté par macadames le 02/02/2005 14:54
    tal:condition="python: here.meta_type=='PloneArticle'"

    Ca devrait marcher ?
  •  • html2pdf

    Posté par fcarlier le 02/02/2005 17:02
    Si je suis sur un plone Article : OK par contre pas sur index_html qui est un document :

    div tal:define="len_text python:len(here.text);"
    tal:condition="python: not(here.meta_type=='PloneArticle')"
    ....
    /div

    div metal:use-macro="python:path(here.getModelPath())"
    tal:condition="python: here.meta_type=='PloneArticle'"
    /div

    +

    Je fais comment pour utiliser utf82iso ??
    div metal:use-macro="python:here.utf2iso(path(here.getModelPath()))"

    cela ne marche pas !!!

    A+ - Florent
  •  • html2pdf

    Posté par fcarlier le 09/02/2005 13:30
    PAS DE REPONSE ??? JE REVIENS A LA CHARGE !!!

    Le truc s'est que je veux améliorer le htmml2pdf !!! en effet, l'icone PDF va now apparaitre partout même au endroit ou il n'existe pas de champs de text ou description !!!

    C'est pourquoi je veux tester le nom de l'objet (PloneArticle, Document) pour faire apparitre l'icone et appliquer le model si possible OU ne pas afficher l'icone pour éviter de générer une erreur !!!

    Je n'arrive plus à mettre sur l'instruction ZPT/Python pour récuperer le nom du produit de l'objet !!!
  •  • html2pdf

    Posté par fcarlier le 09/02/2005 15:55
    Je me réponds à moi même !!!

    il fallait mettre :

    {div tal:condition="python: here.portal_type=='Document'} ..text... {/div}
    {div tal:condition="python: here.portal_type=='PloneArticle'} ..getModelPath... {/div}

    voili !!!
  •  • html2pdf

    Posté par macadames le 09/02/2005 18:20
    Tu nous fais un super html2pdf :cool:
  •  • html2pdf

    Posté par fcarlier le 09/02/2005 18:43
    !!

    Je n'arrive toujours pas à faire un truc du genre :

    div metal:use-macro="python:here.utf2iso(path(here.getModelPath()))"

    D'ailleurs :
    div metal:use-macro="here/document_byline/macros/byline"
    me retourne Created by au lieu de créé par

    Des idées dans l'assistance ??? !!!
  •  • html2pdf

    Posté par macadames le 10/02/2005 12:03
    Moi j'ai fait comme ci-dessous et ça marche en français (j'ai pas vérifié si c'est traduit dans les autres langues).

    D'abord tu mets comme entête html ce qui suit :

    code:
    < html xmlns="http://www.w3.org/1999/xhtml"
          xml:lang="en"
          lang="en"
          tal:attributes="lang site_properties/default_language|default;
                          xml:lang site_properties/default_language|default;" >



    Ensuite tu enlèves toute référence de domaine i18n qui est peut-être mal placée dans ton doc

    Ensuite tu rajoutes après la balise < body > un conteneur div i18n :
    code:
    < div i18n:domain="plone" >


    Ensuite tu fermes ton conteneur < /div > avant le < /body >
    Et ça doit marcher.

    Ce qui est bizarre c'est que le document_byline possède l'attribut i18n

    Moi ça m'amène une autre question, comment on connait la langue en cours d'utilisation par le client en ZPT ?


    A propos de html2pdf ce serait cool de faire un tutoriel finalisé avec toutes les astuces car j'ai pas tout suivi.
  •  • html2pdf

    Posté par fcarlier le 10/02/2005 17:28
    J'ai fait comme tu as dit :

    1/ Je ne vois pas créée par mais si je regarde le source je le vois marqué donc cela doir être une histoire de style

    2/ si je fais index_html/viewPdf je ne vois pas créée mais comme au point 1/
    si je fais index_html/html2pdf, j'ai created by !!! (pourtant html2pdf appel viewPdf !!!)

    Je ne comprend pas !!!!
  •  • html2pdf

    Posté par fcarlier le 10/02/2005 17:35
    Original Message -[02/10/2005]
    Mon viewPdf :
    code:
    div class="documentByLine"
      span Cr&#65533;&#65533; par/span
        <a href="http://10.net/Members/fcarlier"Florent Carlier/a
      br
      spanDerni&#65533;re modification/span
      09-11-2004 17:34
    /div

    et
    pourtant html2Pdf :
    Created by !!!
    Mon viewPdf :
    code:
    div class="documentByLine"
      span Cr&#65533;&#65533; par/span
        a href="http://10.net/Members/fcarlier"Florent Carlier/a
      br
      spanDerni&#65533;re modification/span
      09-11-2004 17:34
    /div

    et
    pourtant html2Pdf :
    Created by !!!
  •  • html2pdf

    Posté par fcarlier le 10/02/2005 18:30
    J'ai trouvé une solution :

    Recopier le contenu de document_byLine dans mon viewPdf et j'ai mis la traduction française en rajoutant un petit utf2iso !!!

    j'aurai préfére éviter de recopier car duplication de code et en plus je perds l'aspect multilangue mais bon, mon viewPdf étant finalement un modele pourquoi pas !!!! il n'a pas forcement à être générique.

    maintenant je cherche à appliquer le script utf2iso sur le retour de getModelPath !!! car mon plonearticle me renvoie de l'utf-8 !!

    A+
  •  • html2pdf

    Posté par macadames le 10/02/2005 21:57
    En fait c'est au niveau de l'external method que ça merde, car pour obtenir le multi-lingue il faut passer une connexion http non ?

    En plus si ton document contient des liens externes comme des images venant d'un autre site ça ne marche pas.

    Moi aussi j'ai perdu le multi-lingue et j'affichais en français grâce à des astuces bidon en fait. Laisse tomber mon histoire de i18n ça ne marchera pas.

    Y a encore un peu de boulot si on veut un truc bien fait.

    Pour l'utf-8 ou autre codage, avec un bon template pdfView basé sur le main_template normalement il n'y a rien à faire, ne pas oublier de passer le charset dans l'entête http car la déclaration dans la page html ne suffit pas.

    Tout ça mériterait un petit produit.
  •  • html2pdf

    Posté par fcarlier le 11/02/2005 11:18
    >Pour l'utf-8 ou autre codage, avec un bon template pdfView basé sur le main_template normalement il >n'y a rien à faire, ne pas oublier de passer le charset dans l'entête http car la déclaration dans la page >html ne suffit pas.

    effectivement meta-type=... charset=iso8859-15 ne suffit pas !! juste pour le viewPdf mais pas pour le html2pdf

    Peux tu redonner la syntaxe ? pour le passer dans l'entête !!?
  •  • html2pdf

    Posté par fcarlier le 11/02/2005 11:37
    Original Message -[02/11/2005]
    même en mettant un truc du genre, en début de fichier :
    tal:block tal:define="dummy python:request.RESPONSE.setHeader('content-type','text/html;; charset=iso8859-15')" /

    cela ne marhe pas !!! il me génére bien la page car passer en iso mais avec des caracteres en vrac !!!
    donc je crois bien que utf2iso reste utile !


    J'ai mis un truc du genre, en début de fichier :
    tal:block tal:define="dummy python:request.RESPONSE.setHeader('content-type','text/html;; charset=iso8859-15')" /

    cela me permet d'avoir un viewPdf correcte (basculement en iso pour affichage)par contre je ne peux pas me passer de utf2iso qui reste utile !

    Le viewPdf peut servir de preview avant génération du PDF.

    reste à trouver une solution pour les metal-use

    Comment on fait que l'adresse retourner, on stocke le résultat html dans une variable pour ensuite utiliser utf2iso
  •  • html2pdf

    Posté par macadames le 11/02/2005 12:42
    Je suis entrain de refaire un pdfView minimal qui marche avec tous les types et qui utilise au maximum la logique du main_template. Il n'y aura plus de pb de codage.

    Il me manque juste cette syntaxe :
    Comment trouver le immediate_view de l'objet en cours d'affichage ?
  •  • html2pdf

    Posté par jpcw2002 le 12/02/2005 09:11
    Voici comment retrouver le immediate view d'un portal type :

    montype = container.portal_types.Event
    mavue=montype.immediate_view
    print mavue
    return printed

    retourne : event_edit_form

    Voili voila
  •  • html2pdf

    Posté par macadames le 12/02/2005 13:57
    Merci jp. ;)

    Le problème avec immediate_view c'est qu'il est souvent laissé de côté par les développeurs de produits ou alors on trouve des valeurs de test, donc pour récupérer le bon template de view j'ai fait un petit script car c'est mission impossible sinon.
    J'ai quand-même laissé le code dans le template (remplacer view_action par initial_view_action) pour ceux qui préfèrent triturer les portal_types.

    Donc pour un pdfView compatible avec tous les templates, voilà d'abord le pdfView template, le css ne sert à rien mais c'est en prévision d'un htmldoc plus élaboré dans l'avenir :

    code:

    < metal:page define-macro="master">< metal:doctype define-slot="doctype">< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">< /metal:doctype>
    < metal:block define-slot="top_slot" />
    < metal:block use-macro="here/global_defines/macros/defines" />
    < html xmlns="http://www.w3.org/1999/xhtml"
         xml:lang="en"
         lang="en"
         tal:attributes="lang site_properties/default_language|default;
                         xml:lang site_properties/default_language|default;">


    < head metal:use-macro="here/header/macros/html_header">

       < metal:baseslot define-slot="base">
         < metal:fillbase fill-slot="base">
           < base href="" tal:attributes="href here/renderBase" />
         < /metal:fillbase>
       < /metal:baseslot>

       < metal:headslot fill-slot="head_slot"
                  tal:define="language here/Language;
                              lang language | site_properties/default_language;
                              charset site_properties/default_charset|string:utf-8">

       < metal:cache use-macro="here/global_cache_settings/macros/cacheheaders">
         Get the global cache headers located in global_cache_settings.
       < /metal:cache>

       < metal:headslot define-slot="head_slot" />
         < !-- A slot where you can insert elements in the header from a template -->
       < /metal:headslot>

       < metal:cssslot fill-slot="css_slot">
           < link rel="stylesheet"
                 type="text/css"
                 href=""
                 tal:attributes="href string:$portal_url/pdfView.css" />
       < /metal:cssslot>

       < metal:javascriptslot fill-slot="javascript_head_slot">
         < !-- A slot where you can insert javascript in the header from a template -->
           < metal:javascriptslot define-slot="javascript_head_slot" />
       < /metal:javascriptslot>
    < /head>

    < body tal:define="typeContent here/portal_type;
                     initial_view_action python: portal.portal_types.getTypeInfo(typeContent).immediate_view;
                     view_action python: here.pdfViewMacro();
                     view_macro python:path('here/%s/macros/main|nothing' % view_action);">


     < tal:principal metal:use-macro="view_macro" />

    < /body>
    < /html>
    < /metal:page> 



    Ensuite mon petit script python qui donne le nom de la bonne vue pour chercher la macro, qui s'appelle pdfViewMacro,
    il faut lui mettre un proxy manager, il utilise en fin de parcours le immediate_view

    code:

    # renvoie le bon template pour la macro

    from Products.CMFCore.utils import getToolByName

    if context.meta_type=='Document':
       return 'document_view'

    elif context.meta_type in ('MonTypeFolder1','MonTypeFolder2','Workgroup','Plone Folder'):
      return 'folder_listing'     

    elif context.meta_type=='CMF Event':
      return 'event_view'

    elif context.meta_type=='Portal File':
     return 'file_view'  

    elif context.meta_type in ('Portal Image','Photo','CMF ZPhoto'):
     return 'image_view'

    elif context.meta_type=='Link':
      return 'link_view'

    elif context.meta_type=='News Item':
      return 'newsitem_view'

    elif context.meta_type=='Portal Topic':
      return 'topic_view'

    elif context.meta_type=='PloneArticle':
      return 'PloneArticle_view' 

    elif context.meta_type=='Newsletter':
      return 'Newsletter_view'

    elif context.meta_type=='NewsletterTheme':
      return 'NewsletterTheme_view'

    elif context.meta_type=='NewsletterTopic':
      return 'NewsletterTopic_view'

    elif context.meta_type == 'MonActualite':
      return 'monactualite_view'

    else :
      try:
          return context.portal_types.getTypeInfo(context).immediate_view
       except: 
          return ''





    Alttention avec le template folder_listing et certains templates de view qui ne respectent pas toutes les règles de templates de view.

    Dans folder listing il faut changer les lignes :

    code:

        < div metal:fill-slot="main"
                tal:define="folderContents python:here.getFolderListingFolderContents(suppressHiddenFiles=1)">



    Par :

    code:

       < div metal:fill-slot="main">

         < tal:main-macro metal:define-macro="main"
                        tal:define="folderContents python:here.getFolderListingFolderContents(suppressHiddenFiles=1)"> 




    et avant la fermeture du calque fermer le tal:main-macro : < /tal:main-macro>

    Pour d'autres templates de view non standards comme PloneArticle il faut faire pareil, ça donne pour PloneArticle_view :

    code:

    < html metal:use-macro="here/main_template/macros/master"
          i18n:domain="plonearticle"
          xmlns="http://www.w3.org/1999/xhtml" 
          xml:lang="en-US"
          lang="en-US">
    < body>
       < div metal:fill-slot="main">
        < tal:main-macro metal:define-macro="main">
          < tal:block tal:condition="container/portal_article/hasLockSupport">
            < div class="documentByLine" tal:condition="here/isLocked">
              < span i18n:translate="">This article is locked by:< /span> < span tal:replace="here/getLockUser" />
            < /div>
            < div class="documentByLine"  tal:condition="not: here/isLocked">
              < span i18n:translate="">This article is not locked.< /span>
              < span i18n:translate="" tal:condition="here/canToggleLock">You must lock this article if you want to edit it.< /span>
            < /div>
          < /tal:block>
          < div metal:use-macro="python:path(here.getModelPath())"></div>
       < /tal:main-macro>
      < /div>
    < /body>
    < /html>



    Ensuite pour l'icône d'action il faut la mettre dans portal_actions et pas sur les portal_types (voir le howto)

    Enfin l'external method html2pdf, je l'ai un peu changée d'après un truc trouvé sur le net.

    code:

    import AccessControl, os 

    def html2pdf(self):
       """ html2pdf converts a HTML-Page to a PDF-Document """

       securityContext=AccessControl.getSecurityManager()
       if securityContext.checkPermission('View', self):

           html = self.pdfView(self,self.REQUEST,self.REQUEST.RESPONSE)
           (stin,stout) = os.popen2('htmldoc --footer " : " --webpage -t pdf --quiet --jpeg -,'b')
           stin.write(html)
           stin.close()
           pdf = stout.read()
           stout.close()

           self.REQUEST.RESPONSE.setHeader('Content-type','application/pdf')
           self.REQUEST.RESPONSE.setHeader('Content-disposition','inline; filename="%s.pdf"' % (self.getId()))

           return pdf

       else:
           raise AccessControl.Unauthorized 



    Par rapport à l'ancienne fonction, il y a un inconvénient c'est que les document_actions apparaissent.
    Mais il suffit de faire un petit traitement sur le html récupéré par l'external method afin de transformer certaines url qui posent problème ou de faire sauter certaines
    parties du code (calque document_actions)
  •  • html2pdf

    Posté par macadames le 13/02/2005 09:46
    Bon j'ai une external method html2pdf qui est un peu mieux, l'autre au dessus faut l'oublier.

    Elle enregistre d'abord le html sur le filesystem du serveur, elle transforme les url d'images relatives en url absolues, on peut appliquer divers traitements supplémentaires au tampon html comme le passage UTF8 -> ISO, ou encore faire disparaitre certaines lignes du code html (document_actions et autres), ajouter un align="left" pour les tableaux ....

    Ce code est un mix du code de dams et d'autres codes trouvés ailleurs, les auteurs qui les ont laissé généreusement trainer se reconnaitront ... ;)

    code:

    # Python imports
    from StringIO import StringIO
    import sys
    import os
    import time
    import re
    import AccessControl
    import cgi

    # CMF imports
    from Products.CMFCore.utils import getToolByName

    # Zope imports
    from zLOG import LOG, ERROR


    def html2pdf(self):
       """
       Convert html document to PDF
       """

       obj_url = self.absolute_url()
       utool = getToolByName(self, 'portal_url')
       uidtool = getToolByName(self, 'uid_catalog')
       portal = utool.getPortalObject()
       portal_path = utool.getPortalPath()
       portal_url = utool()
       temp_path = '/tmp'
       # pour windows temp_path = 'C:/tmp' par exemple
       temp_id = 'PRINT.%s' % str(time.time())
       files_to_unlink =[code]
       pdf_data = None
       # Method to replace link by new one
       def replace_url(match):
           """Compute absolute url
           """
           image = None
           url = str(match.group('url'))
           if match.group('protocol') is not None:
               url = '%s%s' % (match.group('protocol'), url)

           elif url.startswith('/'):
               url= portal_url + url
           else:
               uid = url[5:]
               brains = uidtool(UID=uid)
               if brains:
                   image = brains[0].getObject() 
                   url = image.absolute_url()

           return 'src="%s"' % url 
           return match.group(0) 
         
       filepath = '%s/%s.html' % (temp_path, temp_id)
       html = self.pdfView()
       abs_url = re.compile('src\s*=\s*([\'\"])(?P<protocol>(ht|f)tps?)?(?P<url>[^\"\']*)\\1', re.IGNORECASE)
       html = abs_url.sub(replace_url, html) 

       try:
           fp = open(filepath, "w")
           fp.write(html)
       finally:
           fp.close()
           (stin,stout) = os.popen2('htmldoc --header "..." --footer "..." --webpage -t pdf14 --quiet --jpeg "%s"' % filepath , 'b')
           # version windows :
           # (stin,stout) = os.popen2('C:/htmldoc/ghtmldoc.exe --header "..." --footer "..." --webpage -t pdf14 --quiet --jpeg "%s"' % filepath , 'b')
           stin.close()
           pdf_data = stout.read()
           stout.close()
           files_to_unlink.append(filepath)
           for file_to_unlink in files_to_unlink:
              os.unlink(file_to_unlink)

           self.REQUEST.RESPONSE.setHeader('Content-type','application/pdf')
           self.REQUEST.RESPONSE.setHeader('Content-disposition','inline; filename="%s.pdf"' % (self.getId()))
           return pdf_data 

    [/code]
  •  • html2pdf

    Posté par macadames le 13/02/2005 14:28
    Heu désolé c'était une version intermédiaire de test, voici la version qui marche de html2pdf :

    code:

    # Python imports
    from StringIO import StringIO
    import sys
    import os
    import time
    import re
    import urlparse
    import AccessControl
    import cgi

    # CMF imports
    from Products.CMFCore.utils import getToolByName

    # Zope imports
    from zLOG import LOG, ERROR


    def html2pdf(self):
       """
       Convert html document to PDF
       """

       obj_url = self.absolute_url()
       utool = getToolByName(self, 'portal_url')
       uidtool = getToolByName(self, 'uid_catalog')
       portal = utool.getPortalObject()
       portal_path = utool.getPortalPath()
       portal_url = utool()
       # pour linux
       # temp_path='/tmp'
       temp_path = 'C:/htmldoc/tmp'
       temp_id = 'PRINT.%s' % str(time.time())
       files_to_unlink =[code]
       pdf_data = None
       # Method to replace link by new one
       def replace_url(match):
           """Compute local url
           """
           image = None
           url = str(match.group('url'))
           is_internal_image = True
           if match.group('protocol') is not None:
               url = '%s%s' % (match.group('protocol'), url)

           else:
             try:
                url=urlparse.urljoin (obj_url, url)
             except:
                pass 

           return 'src="%s"' % url 
           return match.group(0) 
         
       filepath = '%s/%s.html' % (temp_path, temp_id)
       html = self.pdfView()
       abs_url = re.compile('src\s*=\s*([\'\"])(?P<protocol>(ht|f)tps?)?(?P<url>[^\"\']*)\\1', re.IGNORECASE)
       html = abs_url.sub(replace_url, html) 

       try:
           fp = open(filepath, "w")
           fp.write(html)
       finally:
           fp.close()
           (stin,stout) = os.popen2('C:/htmldoc/ghtmldoc.exe --header "..." --footer "..." --webpage -t pdf14 --quiet --jpeg "%s"' % filepath , 'b')
           # pour linux
           # (stin,stout) = os.popen2('htmldoc --header "..." --footer "..." --webpage -t pdf14 --quiet --jpeg "%s"' % filepath , 'b')
           stin.close()
           pdf_data = stout.read()
           stout.close()
           files_to_unlink.append(filepath)
           # commenter pour garder les fichiers temporaires
           for file_to_unlink in files_to_unlink:
              os.unlink(file_to_unlink)

           self.REQUEST.RESPONSE.setHeader('Content-type','application/pdf')
           self.REQUEST.RESPONSE.setHeader('Content-disposition','inline; filename="%s.pdf"' % (self.getId()))
           return pdf_data 

    [/code]
  •  • html2pdf

    Posté par fcarlier le 13/02/2005 18:27
    J'ai pas eu le temp de tester encore mais une petite chose,

    pour la gestion de ton fichier temporaire, pourquoi n'utilises tu pas le module tempfile :



    Idée à creuser qui permet de simplifier Linux/Windows, je crois !

    A+
  •  • html2pdf

    Posté par macadames le 13/02/2005 18:55
    Connais pas tempfile.

    En tout cas le truc plus haut marche bien maintenant, tu peux voir les contenus avec identification, ça marche pour tous les types de contenus, la doc est traduite etc ... une seule petite limitation : les images privées ne passent pas, il faudrait les enregistrer en local dans un fichier temporaire, bonne occasion d'utiliser tempfile non ?

    Allez bye.
  •  • html2pdf

    Posté par fcarlier le 13/02/2005 23:38
    Tempfile peut permettre de remplacer :
    code:
       temp_path = '/tmp'
       # pour windows temp_path = 'C:/tmp' par exemple


    par :

    code:
       import tempfile
       ....
       temp_path = tempfile.gettempdir()


    Il va ainsi chercher le repertoire déclarer dans Linux ou Windows comme rep temporaire.
    L'idée est de pouvoir rendre le script générique !!!
  •  • html2pdf

    Posté par fcarlier le 13/02/2005 23:53
    Je commence à tester le scrypt :

    Module /home/fcarlier/Zope-2.7.2-0/Extensions/html2pdf2.py, line 60, in html2pdf
    Module sre, line 179, in compile
    Module sre, line 230, in _compile
    error: unknown specifier: ?P(

    Il ne comprend pas :

    code:
    abs_url = re.compile('src\s*=\s*([\'\"])(?P(ht|f)tps?)?(?P[^\"\']*)\\1', re.IGNORECASE)
    [\code]
  •  • html2pdf

    Posté par macadames le 14/02/2005 08:36
    Normal il ya 2 balises qui ont sauté dedans (forum zopeur)

    Revoilà la syntaxe (enlever espace après balises):

    code:

    abs_url = re.compile('src\s*=\s*([\'\"])(?P< protocol>(ht|f)tps?)?(?P< url>[^\"\']*)\\1', re.IGNORECASE)

  •  • html2pdf

    Posté par fcarlier le 14/02/2005 12:24
    Original Message -[02/14/2005]
    Salut,

    Bon, le script s'est presque du bonheur !!!!

    Par contre, je n'arrive pas à insérer mon unicode.... pour faire mon UTF8 -> ISO
    Il me parle de problème de codec !!!

    A+
    >Salut,
    >
    >Bon, le script s'est presque du bonheur !!!!
    >
    >Par contre, je n'arrive pas à insérer mon unicode.... pour faire mon UTF8 -> ISO
    >Il me parle de problème de codec !!!

    Oups !!! juste aprés html = self.pdfView()
    mettre :
    errors="strict"
    charset="utf-8"
    html = unicode(html, charset, errors).encode("iso-8859-1", errors)

    A+
  •  • html2pdf

    Posté par fcarlier le 14/02/2005 12:29
    Original Message -[02/14/2005]
    ma page est en UTF-8 sauf que les traduction de Plone (créé par, dernière modification) sont déjà en ISO. Je me retrouve avec un problème car il y a deux types de codage dans la même page je pense
    >ma page est en UTF-8 sauf que les traduction de Plone (créé par, dernière modification) sont déjà en ISO. Je me retrouve avec un problème car il y a deux types de codage dans la même page je pense

    J'ai maintenant utilisé ton pdfView !!!!

    mettre /
    code:
     < div metal:use-macro="python:path(here.getModelPath())"/>


    sinon, j'ai remplace le nom du PloneArticle_view par PloneArticle_view_html2pdf pour ne pas affecter l'usage normal de PloneArticle
  •  • html2pdf

    Posté par fcarlier le 14/02/2005 14:02
    Voici le code à rajouté aprés html = self.pdfView()

    code:
       # Suppression documentActions
       try:
         del_docactions = re.compile('(.*)(< div class="documentActions">.*?< /div>)(..
    *)', re.I |re.DOTALL)
         matchs = del_docactions.search( html )
         html = '%s%s' % (matchs.group(1), matchs.group(3))
       except:
         pass

    Attention espace aprés < !!

    Sinon, tu as qq version de plone macadames car moi su Plone 2.04, mon folder_listing est différent de ceux que tu marques !
  •  • html2pdf

    Posté par macadames le 14/02/2005 16:38
    Bah j'ai plusieurs versions de Plone et de folder_listing. Avec celui de plone 2.04 c'est encore plus facile, il suffit de remplacer :
    code:
        < div metal:fill-slot="main">


    par

    code:
        < div metal:fill-slot="main">
          < tal:main-macro metal:define-macro="main">


    et de rajouter < /tal:main-macro> avant le < /div> de fermeture du block div fill-slot


    C'est juste le principe des macros qu'il faut comprendre, c'est toujours pareil.

    Concernant folder_listing, ce qui serait intéressant plutôt que d'en faire un pdf, c'est de faire un document pdf qui contient chaque traduction pdf des objets à l'intérieur du folder et une table des matières en tête de fichier. htmldoc peut faire ça en ligne de commande. C'est l'idée de dams que je trouve super, et ça doit pas être trop dur à faire.

    Merci pour la suppression des documents actions ;)

    Concernant l'encodage c'est pas très bon d'avoir des mélanges iso utf8 sur une page, ya un blèm sur ton site.
  •  • html2pdf

    Posté par fcarlier le 14/02/2005 17:30
    > Concernant l'encodage c'est pas très bon d'avoir des mélanges iso utf8 sur une page, ya un blèm sur ton site.

    corrigé, je pense !!!!

    Tous marche bien pour le moment !!

    Par contre, je dois encore regarde le principe car par exemple, mon CMFBOARD ne veut pas me générer de pdf :

    Type de l'erreur
    KeyError
    Valeur de l'erreur
    'header_macro'

    et quand un type n'est pas reconnu par pdfView, j'ai :
    Type de l'erreur
    TypeError
    Valeur de l'erreur
    len() of unsized object

    pas trés beau !!!!

    idée interessante de réécrire un folder_listing adaptés à la génération d'un pdf avec sommaire !!!!
  •  • html2pdf

    Posté par macadames le 14/02/2005 18:37
    Pour CMF Board, voir dans le header_macro de pdfView si il n'y a pas une incompatibilité, ça doit pas être grand chose. Envoie le Traceback de l'erreur.

    L'autre erreur c'est lorsque il manque

    code:

     < tal:main-macro metal:define-macro="main">



    sur le template de view ou bien lorsqu'il n'y a pas de template view défini dans le script pdfViewMacro ni de immediate_view dans le portal_type.

    Même si ça ne sert pas à grand-chose modifie le pdfView :

    code:

     < tal:principal metal:use-macro="view_macro"
                          tal:condition="view_action" />





    Faudrait peut-être arrêter là ce post et refaire un howTo complet non ? ça devient top long.

    > idée interessante de réécrire un folder_listing adaptés à la génération d'un pdf avec sommaire !!!!

    Je sens qu'il va y avoir encore des posts sur le sujet.

    Sinon il parait qu'il existe des trucs tout faits et ultra performants : http://www.reportlab.com



    On est pas des zopeurs mais des mazopeurs.
  •  • html2pdf

    Posté par fcarlier le 14/02/2005 21:18
    voici le traceback :
    code:
    Traceback (innermost last):
      Module ZPublisher.Publish, line 101, in publish
      Module ZPublisher.mapply, line 88, in mapply
      Module ZPublisher.Publish, line 39, in call_object
      Module Products.ExternalMethod.ExternalMethod, line 225, in __call__
       - __traceback_info__: ((< ForumFolder at /zopex10/forums>,), {}, None)
      Module /home/fcarlier/Zope-2.7.2-0/Extensions/html2pdf.py, line 57, in html2pdf
      Module Shared.DC.Scripts.Bindings, line 306, in __call__
      Module Shared.DC.Scripts.Bindings, line 343, in _bindAndExec
      Module Products.PageTemplates.ZopePageTemplate, line 222, in _exec
      Module Products.PageTemplates.PageTemplate, line 96, in pt_render
       - < ZopePageTemplate at /zopex10/pdfView used for /zopex10/forums>
      Module TAL.TALInterpreter, line 189, in __call__
      Module TAL.TALInterpreter, line 233, in interpret
      Module TAL.TALInterpreter, line 649, in do_defineMacro
      Module TAL.TALInterpreter, line 233, in interpret
      Module TAL.TALInterpreter, line 408, in do_optTag_tal
      Module TAL.TALInterpreter, line 393, in do_optTag
      Module TAL.TALInterpreter, line 388, in no_tag
      Module TAL.TALInterpreter, line 233, in interpret
      Module TAL.TALInterpreter, line 670, in do_useMacro
      Module TAL.TALInterpreter, line 233, in interpret
      Module TAL.TALInterpreter, line 408, in do_optTag_tal
      Module TAL.TALInterpreter, line 393, in do_optTag
      Module TAL.TALInterpreter, line 388, in no_tag
      Module TAL.TALInterpreter, line 233, in interpret
      Module TAL.TALInterpreter, line 656, in do_useMacro
      Module Products.PageTemplates.TALES, line 221, in evaluate
       - URL: /zopex10/pdfView
       - Line 66, Column 8
       - Expression: standard:'header_macro'
       - Names:
          {'container': < PloneSite instance at 43fb4380>,
           'context': < ForumFolder at /zopex10/forums>,
           'default': < Products.PageTemplates.TALES.Default instance at 0x40c03f6c>,
           'here': < ForumFolder at /zopex10/forums>,
           'loop': < SafeMapping instance at 43d835b0>,
           'modules': < Products.PageTemplates.ZRPythonExpr._SecureModuleImporter instance at 0x40c073ec>,
           'nothing': None,
           'options': {'args': ()},
           'repeat': < SafeMapping instance at 43d835b0>,
           'request': < HTTPRequest, URL=http://zopex10.bigrob.net/forums/html2pdf>,
           'root': < Application instance at 43fb4320>,
           'template': < ZopePageTemplate at /zopex10/pdfView used for /zopex10/forums>,
           'traverse_subpath':[code],
           'user': fcarlier}
      Module Products.PageTemplates.Expressions, line 201, in __call__
      Module Products.PageTemplates.Expressions, line 189, in _eval
      Module Products.PageTemplates.Expressions, line 141, in _eval
       - __traceback_info__: header_macro
    KeyError: 'header_macro'
    [/code]
  •  • html2pdf

    Posté par fcarlier le 14/02/2005 21:21
    >posté: 26.01.2005 - 11:21
    >
    >Bonjour,
    >
    >Je relance le sujet sur html2pdf !!

    J'ai bien fait de relancer le sujet !!!! maintenant je pense que le html2pdf est bien abouti !!

    Macadames demande à dams de pouvoir refaire et corriger son How-To

    sinon, pour reportlab, jamais vraiment réussi à le prendre en main !!!! enfin, si Gillou veut nous faire un How-to qui remplace html2pdf en puissance 10, je suis preneur !!!!!
  •  • html2pdf

    Posté par macadames le 16/02/2005 11:32
    J'ai trouvé sur Zopera la solution pour faire le book pdf à partir d'un folder.

    Il suffit de générer un template qui met les contenus les uns en dessous des autres dans une seule page.

    Il faudra mettre un test pour savoir si le contenu est un conteneur ou pas soit dans l'external method (ce serait mieux) ou dans portal_actions.

    Il suffit juste de mettre le commentaire < !&#8722;&#8722; NEW PAGE &#8722;&#8722;> entre chaque contenu et de mettre l'option table des matières sur htmldoc.

    Pour mettre les contenus à la queuleuleu :

    http://www.zopera.org/Members/kikan/ForumPost.2005-02-14.1506

    Ya pluka et voilà.
  •  • html2pdf

    Posté par dams le 16/02/2005 17:23
    Euh dams, il a lu un peu le truc mais il a pas tt suivi ;)
    Mais y a pas de probleme, je peux faire la secretaire et reecrire tt ca.
    fo juste me renvoyer par mail tt les infos et pis je vous fais ca.
    Et a la rigeur creee un nouveau post dans Projet Tutore.

    a tt
  •  • Re: html2pdf

    Posté par gillou le 01/03/2005 21:18
    zyon wrote:
    >posté: 26.01.2005 - 11:21
    ...
    sinon, pour reportlab, jamais vraiment réussi à le prendre en main !!!! enfin, si Gillou veut nous faire un How-to qui remplace html2pdf en puissance 10, je suis preneur !!!!!


    Howto...

    Allons, Reportlab n'est pas si difficile à utiliser. En utilisant directement platypus et non en faisant joujou en direct avec le "canvas" (très bas niveau), on arrive rapidement à des résultats sympa. N'essaie pas d'intégrer directement dans Zope/Plone (CPS, Silva, excusez-moi ceux que je ne mentionne pas...) mais essaie en mode console avant, ça ira plus vite pour apprendre. L'intégration à Zope/Plone coulera de source par la suite. Je l'ai utilisé pour faire un catalogue qualité "print" avec des codes barres (impossible à placer avec html2pdf).

    Attention, il faut également convertir en latin 1, l'UTF-8 n'était pas supporté la dernière fois que j'ai fait joujou avec. Peut-être les dernières versions de reportlab supportent maintenant l'UTF-8, à voir.

    La doc de reportlab et platypus est très bien faite et fourmille d'exemples.

    Pierre-Julien a glissé chez sourceforge (projet ingeniweb) un tool Plone qui facilite le boulot avec un modèle de base qui peut facilement être adapté aux schémas de tes types perso.

    Une autre solution de luxe (la démo est soufflante), est d'utiliser le product RMLPageTemplate...

    http://www.zope.org/Members/mkerrin/RMLPageTemplate

    ...qui fonctionne parfaitement sous Plone (CPS, Silva, Zwook, Ikaroo...), enfin n'importe quel truc Zope.

    Bon, ça nécessite d'apprendre le langage RML, une sorte de XSL-FO simplifié, mais comme tu y accèdes à travers des ZPT, tu peux toujours faire des macros (as usual) pour tes formes les plus usitées.
  •  • Re: html2pdf

    Posté par macadames le 02/03/2005 21:01
    Bon ben je vais regarder avant de trop s'enfoncer dans html2pdf qui obligerait à descendre dans ses sources pour qq chose de propre.

    C'est qq chose de très intéressant le pdf associé à des workflows sécurisés (voir les billets de train sncf par exemple).

    A creuser absolument. merci pour toutes ces infos, quant aux sources disponibles sur le sourceforge d'ingeniweb je ne sais pas si il faut dire merci quand on s'est déjà servi ;)