pythonhtmldjangopdfpisa

pisa html to pdf issue with greek stressed letters used with django


I am using pisa to generate a pdf from html in a django application. My view code is the following

if request.method == 'POST':        
    return write_to_pdf(request.POST['convert'], { }, 'file')

where convert is a TextArea from which i get the value to write on my pdf file

write_to_pdf

def fetch_resources(uri, rel):
    path = '%s/media/pdf/' % RHOMBUS_PATH
    return path

def write_to_pdf(template_data, context_dict, filename):
    print template_data
    template = Template(template_data)
    context = Context(context_dict)
    html = template.render(context)
    print html
    result = StringIO.StringIO()
    pdf = pisa.CreatePDF(html.encode('UTF-8'), result, link_callback=fetch_resources, encoding='UTF-8')
    print result.getvalue()

    if not pdf.err:
        response = http.HttpResponse(mimetype='application/pdf')
        response['Content-Disposition'] = 'attachment; filename=%s.pdf' % filename
        response.write(result.getvalue())
        return response
    return http.HttpResponse('Problem creating PDF: %s' % cgi.escape(html))

The generated pdf though has a problem when the TextArea has greek stressed characters like

ά έ 

etc. I tried changing the encodings but nothing. Any help would be appreciated.


Solution

  • I also had this issue with Greek characters (instead of stressed characters I received black boxes). As a first step you need to change your font to a proper one (like dejavu sans). To do this, add a style element to your html template like this:

    <style type='text/css'>
    
        @font-face {
            font-family: "DejaVuSansMono";
            src: url("fonts/DejaVuSansMono.ttf");
        }
    
        @font-face {
            font-family: "DejaVuSansMono";
            src: url("fonts/DejaVuSansMono-Bold.ttf");
            font-weight: bold;
        }
        @font-face {
            font-family: "DejaVuSansMono";
            src: url("fonts/DejaVuSansMono-Oblique.ttf");
            font-style: italic, oblique;
        }
        @font-face {
            font-family: "DejaVuSansMono";
            src: url("fonts/DejaVuSansMono-BoldOblique.ttf");
            font-weight: bold;
            font-style: italic, oblique;
        }
    
        *, html {
            font-family: "DejaVuSansMono";
        }
    
        html {
            padding:10pt;
        }
    
    </style>
    

    Now, the dejavusans font can be downloaded from http://dejavu-fonts.org/wiki/Main_Page. Also, there are various issues with the location that you will put the font files - I have provided some insight on my answer to trouble in converting unicode template to pdf using xhtml2pdf. As a first step, I propose to put these fonts in C:/fonts (or /tmp/fonts if using unix) and use the absolute url for @font-face, for instance

    @font-face {
        font-family: "DejaVuSansMono";
        src: url("c:/fonts/DejaVuSansMono.ttf");
    }
    

    After that, check my answer to see how you can use relative urls.

    Finally, I have to mention that I've only tested the above with dejavu-sans (and it works fine) - however I'd really like to know if the above solution works fine with other fonts, like Calibry - if you test it please provide feedback.

    If the above doesn't work, please take a look at the render_to_pdf function I use:

    def render_to_pdf(template_src, context_dict):
        template = get_template(template_src)
        context = Context(context_dict)
        html  = template.render(context)
        result = StringIO.StringIO()
    
        pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), result, path= settings.PROJECT_PATH) 
    
        if not pdf.err:
            return HttpResponse(result.getvalue(), content_type='application/pdf')
        return HttpResponse('<pre>%s</pre>' % escape(html))