【问题标题】:ReportLab PDF Python 3 problems with fontsReportLab PDF Python 3 字体问题
【发布时间】:2020-09-26 23:46:18
【问题描述】:

我想生成不同语言的 PDF 报告。 我遵循了使用 TTFont 的不同指南。 我尝试过使用不同的语言,但没有一种可以工作。

例如,对于俄语,我使用:

self.buffer = BytesIO()
self.pdf_data = []

pdfmetrics.registerFont(TTFont('DejaVuSerif', self.font_dir + 'dejavuserif/DejaVuSerif.ttf'))
font_name = "DejaVuSerif"

self.styles = getSampleStyleSheet()
self.styles.add(ParagraphStyle(name = "HeaderTitle", parent = self.styles['Title'], alignment = TA_CENTER, fontName=font_name))


doc = SimpleDocTemplate(self.buffer)
self.pdf_data.append(Paragraph('Операции - Отчет Август 2020 г.', self.styles['HeaderTitle']))

doc.build(self.pdf_data)
pdf = self.buffer.getvalue()
self.buffer.close()

但是输出是:

€•‚ƒ„…†† - €‡ˆ‚‡ „‰Š‹Œ‡ 2020 Š.

我做错了什么?

ReportLab 版本 = 3.5.50

更新

我想指出,在语言环境中文件是正确的,但是当我在响应中附加时,问题仍然存在。

return flask.send_from_directory(file_path, filename, mimetype="application/pdf", as_attachment=True, attachment_filename=filename, cache_timeout=0)

【问题讨论】:

    标签: python-3.x reportlab


    【解决方案1】:

    您显示的代码部分看起来不错。在变量“pdf”中,您可以取回 PDF 的字节数。

    人们可以用这样的烧瓶响应返回字节:

    @app.route('/')
    def gen_pdf():
        pdf_util = PDFUtil()
        pdf_bytes = pdf_util.generate()
        response = make_response(pdf_bytes)
        response.headers.set('Content-Type', 'application/pdf')
        return response
    

    请注意,Content-Type 标头需要设置为:application/pdf。如果您希望浏览器下载 PDF 文件而不是内联显示,您可以添加额外的标题,例如:

    response.headers.set('Content-Disposition', 'attachment', filename='test.pdf')
    

    因此,如果字体很好,并且这些字节以 content-type application/pdf 返回,则正确的结果将显示在浏览器中。

    我只是稍微修改了你的代码,将它保存在一个名为 pdf_flask_demo.py 的 python 脚本中,以获得一个带有烧瓶响应部分的独立示例:

    from io import BytesIO
    
    from reportlab.lib.enums import TA_CENTER
    from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont
    from reportlab.platypus import SimpleDocTemplate, Paragraph
    from flask import Flask, make_response
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def gen_pdf():
        pdf_util = PDFUtil()
        pdf_bytes = pdf_util.generate()
        response = make_response(pdf_bytes)
        response.headers.set('Content-Type', 'application/pdf')
        return response
    
    
    class PDFUtil:
        def __init__(self):
            self.font_dir = "./"
    
        def generate(self):
            self.buffer = BytesIO()
            self.pdf_data = []
    
            pdfmetrics.registerFont(TTFont('DejaVuSerif', self.font_dir + 'dejavuserif/DejaVuSerif.ttf'))
            font_name = "DejaVuSerif"
    
            self.styles = getSampleStyleSheet()
            self.styles.add(
                ParagraphStyle(name="HeaderTitle", parent=self.styles['Title'], alignment=TA_CENTER, fontName=font_name))
    
            doc = SimpleDocTemplate(self.buffer)
            self.pdf_data.append(Paragraph('Операции - Отчет Август 2020 г.', self.styles['HeaderTitle']))
    
            doc.build(self.pdf_data)
            pdf = self.buffer.getvalue()
            self.buffer.close()
            return pdf
    

    替代方案

    也可以将PDF文件保存在本地文件系统中并返回flask.send_from_directory。用户浏览器上下载的 PDF 在 PDF 查看器中打开时也可以正确显示。

    @app.route('/')
    def gen_pdf():
        pdf_util = PDFUtil()
        pdf_bytes = pdf_util.generate()
        f = open('/Users/stephan/tmp/mytest.pdf', 'wb')
        f.write(pdf_bytes)
        f.close()
        return flask.send_from_directory('/Users/stephan/tmp/', 'mytest.pdf', mimetype="application/pdf", as_attachment=True,
                                         attachment_filename='mytest.pdf', cache_timeout=0)
    

    测试

    在命令行我调用:

    export FLASK_APP=pdf_flask_demo
    export FLASK_ENV=development 
    flask run
    

    当在浏览器中使用http://127.0.0.1:5000 时,我得到了想要的结果:

    【讨论】:

    • 谢谢斯蒂芬。它几乎可以解决我的问题(也许在此更改之前它也可以正常工作)。当我将文件作为 Web 响应发送时,问题仍然存在。我在语言环境中得到了正确的文件(我没有在该文件之前检查过)但是当我将它附加到 Flask 响应时,文件的字符错误
    • 感谢您的更新。您使用的代码与我使用的相同。但是,在语言环境中,当我使用“flask.send_from_directory”发送该文件时,该文件会正确生成,但该文件带有错误的字符。发送字节是我在您最初回复之前使用的方法
    • PS:我会继续努力的。如果没有其他有用的回复,我将奖励您在回复中付出的努力
    • 好的...解决了问题。我正确地完成了所有过程。显然问题不在我搜索的地方。我使用ajax下载pdf。破坏pdf的是ajax。
    猜你喜欢
    • 2023-04-07
    • 2021-03-09
    • 2011-02-15
    • 2016-05-09
    • 2014-05-22
    • 2017-04-09
    • 2016-02-22
    • 2011-04-06
    • 1970-01-01
    相关资源
    最近更新 更多