6

我一直在尝试从可以是英语、波斯语、数字或它们的组合的内容创建 PDF 文件。

波斯语文本存在一些问题,例如:“این یک متن فارسی است”

1-文字必须从右向左书写

2-单词中不同位置的字符之间存在差异(意味着字符根据周围的字符改变形状)

3-因为句子是从右到左阅读的,所以正常的文本换行不能正常工作。

4

3 回答 3

8

我使用reportlab 来创建PDF,但不幸的是reportlab 不支持阿拉伯语和波斯语字母,所以我使用Vahid Mardani 的'rtl' 库和Meir Kriheli 的'pybidi' 库来使文本在PDF 结果中看起来正确。

首先我们需要在reportlab中添加一个支持波斯语的字体:

  1. 在 Ubuntu 14.04 中:

    copy Bahij-Nazanin-Regular.ttf into
    /usr/local/lib/python3.4/dist-packages/reportlab/fonts folder
    
  2. 将字体和样式添加到 reportlab:

    from reportlab.lib.enums import TA_RIGHT
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont
    pdfmetrics.registerFont(TTFont('Persian', 'Bahij-Nazanin-Regular.ttf'))
    styles = getSampleStyleSheet()
    styles.add(ParagraphStyle(name='Right', alignment=TA_RIGHT, fontName='Persian', fontSize=10))
    

在下一步中,我们需要将波斯文本 Letters 重塑为正确的形状,并使每个单词的方向从右到左:

    from bidi.algorithm import get_display
    from rtl import reshaper
    import textwrap

    def get_farsi_text(text):
        if reshaper.has_arabic_letters(text):
          words = text.split()
          reshaped_words = []
          for word in words:
            if reshaper.has_arabic_letters(word):
              # for reshaping and concating words
              reshaped_text = reshaper.reshape(word)
              # for right to left    
              bidi_text = get_display(reshaped_text)
              reshaped_words.append(bidi_text)
            else:
              reshaped_words.append(word)
          reshaped_words.reverse()
         return ' '.join(reshaped_words)
        return text

对于添加项目符号或包装文本,我们可以使用以下函数:

    def get_farsi_bulleted_text(text, wrap_length=None):
       farsi_text = get_farsi_text(text)
       if wrap_length:
           line_list = textwrap.wrap(farsi_text, wrap_length)
           line_list.reverse()
           line_list[0] = '{} •'.format(line_list[0])
           farsi_text = '<br/>'.join(line_list)
           return '<font>%s</font>' % farsi_text
       return '<font>%s &#x02022;</font>' % farsi_text

为了测试我们可以编写的代码:

    from reportlab.lib.pagesizes import letter
    from reportlab.platypus import SimpleDocTemplate, Paragraph
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle

    doc = SimpleDocTemplate("farsi_wrap.pdf", pagesize=letter,    rightMargin=72, leftMargin=72, topMargin=72,
                    bottomMargin=18)
    Story = []

    text = 'شاید هنوز اندروید نوقا برای تمام گوشی‌های اندرویدی عرضه نشده باشد، ولی اگر صاحب یکی از گوشی‌های نکسوس یا پیک' \
   'سل باشید احتمالا تا الان زمان نسبتا زیادی را با آخرین نسخه‌ی اندروید سپری کرده‌اید. اگر در کار با اندروید نوقا' \
   ' دچار مشکل شده‌اید، با دیجی‌کالا مگ همراه باشید تا با هم برخی از رایج‌ترین مشکلات گزارش شده و راه حل آن‌ها را' \
   ' بررسی کنیم. البته از بسیاری از این روش‌ها در سایر نسخه‌های اندروید هم می‌توانید استفاده کنید. اندروید برخلاف iOS ' \
   'روی گستره‌ی وسیعی از گوشی‌ها با پوسته‌ها و اپلیکیشن‌های اضافی متنوع نصب می‌شود. بنابراین تجویز یک نسخه‌ی مشترک برا' \
   'ی حل مشکلات آن کار چندان ساده‌ای نیست. با این حال برخی روش‌های عمومی وجود دارد که بهتر است پیش از هر چیز آن‌ها را' \
   ' بیازمایید.'
    tw = get_farsi_bulleted_text(text, wrap_length=120)
    p = Paragraph(tw, styles['Right'])
    Story.append(p)
    doc.build(Story)
于 2016-12-27T14:00:34.427 回答
5

在使用 Reportlab 工作了一段时间后,我们在组织和格式化它时遇到了一些问题。这花了很多时间,而且有点复杂。所以我们决定使用 pdfkit 和 jinja2。这样我们可以用 html 和 CSS 格式化和组织,我们也不需要重新格式化波斯文本。

首先,我们可以设计一个 html 模板文件,如下所示:

    <!DOCTYPE html>
        <html>
        <head lang="fa-IR">
            <meta charset="UTF-8">
            <标题></标题>
        </head>
        <正文>
            <p dir="rtl">سوابق کاری</p>
            <ul dir="rtl">
                {% 体验经验 %}
                <li><a href="{{ experience.url }}">{{ experience.title }}</a></li>
                {% endfor %}
            </ul>
        </正文>
        </html>

然后我们使用 jinja2 库将我们的数据渲染成模板,然后使用 pdfkit 从渲染结果创建一个 pdf:

    from jinja2 import Template
    from pdfkit import pdfkit

    sample_data = [{'url': 'http://www.google.com/', 'title': 'گوگل'},
                   {'url': 'http://www.yahoo.com/fa/', 'title': 'یاهو'},
                   {'url': 'http://www.amazon.com/', 'title': 'آمازون'}]

    with open('template.html', 'r') as template_file:
        template_str = template_file.read()
        template = Template(template_str)
        resume_str = template.render({'experiences': sample_data})

        options = {'encoding': "UTF-8", 'quiet': ''}
        bytes_array = pdfkit.PDFKit(resume_str, 'string', options=options).to_pdf()
        with open('result.pdf', 'wb') as output:
            output.write(bytes_array)
于 2017-03-11T15:44:59.597 回答
4

如果有人想使用 html 模板生成 pdf Django,可以这样做:

template = get_template("app_name/template.html")
context = Context({'something':some_variable})
html = template.render(context)
pdf = pdfkit.from_string(html, False)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=output.pdf'
return response
于 2017-07-29T09:15:57.890 回答