【问题标题】:How to get PDF output to look exactly like HTML output如何使 PDF 输出看起来与 HTML 输出完全相同
【发布时间】:2018-07-28 11:48:03
【问题描述】:

我正在尝试为我的客户创建一个 PDF,以便开始为他们的客户开具发票。我过去处理过创建 PDF,并记得创建它们是一个巨大的痛苦。在我的 Django 应用程序中,我有两个视图函数,一个仅呈现用于设计发票的模板,另一个将其转换为 pdf 并呈现 PDF。我有两个并排打开的选项卡,一个指向每个版本的模板 HTML 和 PDF,它们看起来完全不同。我必须使用一种特殊的标记语言来创建 PDF,还是它们的 python 包将 HTML 转换为 PDF 中该 HTML 的精确副本?

查看函数

from django.shortcuts import render, HttpResponse
from django.template.loader import get_template

from io import BytesIO
from xhtml2pdf import pisa


def generate_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html = template.render({})
    result = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return None

def ronin(request):
    template = get_template('ronin.html')
    context = {}
    html = template.render(context)
    pdf = generate_pdf('ronin.html', context)
    if pdf:
        response = HttpResponse(pdf, content_type='application/pdf')
        filename = "Invoice_%s.pdf" % ("12341231")
        content = "inline; filename='%s'" % (filename)
        download = request.GET.get("download")
        if download:
            content = "attachment; filename='%s'" % (filename)
        response['Content-Disposition'] = content
        return response
    return HttpResponse("Not found")

def ronin_html(request):
    template = 'ronin.html'
    context = {}

    return render(request, template, context)

HTML

<!DOCTYPE html>
<html>

<head></head>

<body style="margin: 0;">

<style>
    #invoice-template {
        padding: 100px 100px 50px 100px
    }

    table {
        border-collapse: collapse;
    }

    table#main {
        border-bottom: 1px solid darkgray; width: 100%;
    }

    td.header.first {
        border-bottom: 1px solid darkgray;
        border-right: 1px solid darkgray;
        padding: 1% 4%;
        width: 20%;
    }

    td.header.second {
        padding: 0;
        vertical-align: top;
    }

    td.header.second .contact-details td {
        padding: 15px;
    }

    td.header.second .address td {
        padding: 15px;
    }

    td.header.second p {
        margin: 0;
    }
</style>

<div id="invoice-template">

    <table id="main" cellspacing="0">
        <tr>
            <td class="header first">
                <img src="/static/images/logo_dark.png" alt="">
            </td>
            <td class="header second">
                <table>
                    <tr class="address">
                        <td>
                            <p>ADDRESS</p>
                            <p>ADDRESS EXAMPLE St. CITY, STATE 11111</p>
                        </td>
                    </tr>
                    <tr class="contact-details">
                        <td>
                            <p>PHONE</p>
                            <p>+1 111 222 3333</p>
                        </td>
                        <td>
                            <p>WEBSITE</p>
                            <p>Website.com</p>
                        </td>
                        <td>
                            <p>FOCUS</p>
                            <p>WEBSITES / MOBILE APPS</p>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>

</div>

HTML 视图

PDF 查看

【问题讨论】:

  • 如果您希望您的 PDF 看起来 完全 像 HTML 那样:它们有不同的目标,所以这是不可能的。最接近 HTML 的屏幕截图。
  • 也许您可以从浏览器打印到 pdf,尽管打印也会改变外观。总是可以在 PDF 中嵌入屏幕截图 - 很傻,但我已经看到了。

标签: html django pdf


【解决方案1】:

您将遇到大多数 HTML 到 PDF 库的渲染问题,尤其是当它们使用 WebKit 作为引擎时。我建议使用 Puppeteer(创建页面的无头 chrome 实例并截取屏幕截图,这将是页面的真正 1:1 副本)和 PDFKit 的组合来获取这些图像并将它们附加到 pdf 文档.

当然,这取决于您是否知道发票不会比完整的 PDF 页面大,或者如果是,您需要知道如何将内容分成单独的页面。

如果您真的想要 PDF 格式的 1:1 副本,这些都是需要解决的难题。

否则,我建议使用 wkhtmltopdf 之类的东西来获得相当好的近似值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2019-03-05
    • 1970-01-01
    • 2015-03-25
    • 2018-04-28
    相关资源
    最近更新 更多