UnicodeEncodeError: кодек 'latin-1' не может кодировать символы в позиции 2082-2084: ordinal not in range(256)

Я не знаю, почему это происходит. Всякий раз, когда я добавляю арабский контент, он показывает вышеуказанную ошибку, в противном случае он работает нормально с английским языком. Тот же код прекрасно работает в другом проекте, но не здесь. views.py

def generate_pdf_for_gift_and_add_to_cart(request):
    cart = Cart(request)
    if request.method == 'POST':
        id = request.POST.get('project_id')
        selectedAmount = request.POST.get('amount')
        senderNameDonatedDonationPage = request.POST.get(
            'senderNameDonatedDonationPage')
        receiverNameDonatedDonationPage = request.POST.get(
            'receiverNameDonatedDonationPage')
        phoneNumberDonatedDonationPage = request.POST.get(
            'phoneNumberDonatedDonationPage')
        emailDonatedDonationPage = request.POST.get('emailDonatedDonationPage')
        params = {
            "project_id": id,
            "selectedAmount": selectedAmount,
        }

        pdf = render_to_pdf('pdfs/gift_pdf.html', params)
        if pdf:
            response = HttpResponse(pdf, content_type='application/pdf')
            filename = f"Invoice_{emailDonatedDonationPage}_{datetime.now()}.pdf"
            content = "inline; filename='%s'" % filename
            download = request.POST.get("download")
            if download:
                content = "filename='%s'" % filename
            response['Content-Disposition'] = content
            receipt_file = BytesIO(pdf.content)
            return response

utils.py Я также попробовал кодировку utf-8, но это показывает мне пустые поля на сгенерированной странице pdf.

from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa


def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html = template.render(context_dict)
    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

gift_pdf.html. ниже приведен пример шаблона, в котором будет отображаться это.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gift PDF</title>

    <style type="text/css">
        @page {
            size: 6in;
        }

        body {
            margin: 0;
        }

        .page_body {
            background-image: url("");
            background-position: center center;
            background-repeat: no-repeat;
            background-size: cover;
            position: relative;
            width: 100%;
        }

        .page_body .content_row {
            display: flex;
            justify-content: center;
            align-items: center;
            grid-gap: 127px;
            margin: 630px 0;
            padding: 0 78px;
            flex-direction: column;
        }

        .page_body .ehdaa {
            position: absolute;
            top: 33px;
            left: 20%;
            width: 625px;
            height: 495px;
        }

        .page_body .flowers {
            position: absolute;
            top: 0;
            right: 0;
        }

        .page_body p {
            line-height: 10px;
            font-size: 15px;
            font-weight: 700;
            text-align: center;
        }

        .page_body .headings {
            color: #B1915A;
        }

        .page_body .paragraph {
            color: #1F858F;
        }

        .page_body .hands {
            position: absolute;
            left: 0;
            bottom: 0;
            width: 370px;
            height: auto;
        }
    </style>

</head>

<body>

<div class="page_body container-fluid">
    <img class='ehdaa' src="" alt="ehda">
    <img class='flowers' src=""
         alt="flowers">
    <div class="content_row">

        <div class="headings">{{ receiverNameDonatedDonationPage }}إلي</div>

    </div>
    <img class="hands" src=""
         alt="hands">
</div>
</body>

</html>

Ваш код нуждается в нескольких доработках, чтобы работать без генерации блочных символов в выводе.

  1. Добавьте шрифт, поддерживающий арабский язык

По умолчанию xhtml2pdf предоставляет лишь несколько шрифтов , ни один из которых не поддерживает арабский язык:

Times-Roman: Times New Roman, Times, Georgia, serif
. Helvetica: Arial, Verdana, Geneva, sansserif, sans
. Courier: Courier New, monospace, monospaced, mono
ZapfDingbats
Символ

Итак, вы хотите добавить шрифт в ваш HTML файл, который создаст font-face, который

   <style type="text/css">
        @font-face {
            font-family: ArialUnicode;
            src: url("static/Arial Unicode.ttf")
        }
        <!-- other stuff here -->
        body {
            margin: 0;
            font-family: "ArialUnicode", sans-serif;
        }
        
        <!-- more css here -->
   </style>
  1. Измените кодировку на utf-8

Это относится к вашей строке:

pdf = pisa.pisaDocument(BytesIO(template.encode("ISO-8859-1")), result)

Вы также можете использовать ISO-8859-6, если у вас совместимый шрифт, но я использую Arial Unicode в моем примере, поэтому я использую utf-8 в качестве кодировки.


Вот чрезвычайно сжатая версия вашего кода, которая просто загружает ваш HTML файл и запускает его через xhtml2pdf.pisa

from io import BytesIO

from xhtml2pdf import pisa

# I have a templates directory with the html file in it
# and a 'static' directory with fonts in it


if __name__ == '__main__':
    with open("templates/gift_pdf.html") as t:
        template = t.read()

    result = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(template.encode("utf-8")), result)
    with open("output.pdf", "w+b") as ofile:
        ofile.write(result.getbuffer())

Вывод выглядит следующим образом:

enter image description here

Если вы хотите скачать pdf страницы html

<div id="content">
     <h3>Hello, this is a H3 tag</h3>

    <p>A paragraph</p>
</div>
<button onclick="CreatePDFfromHTML()">generate PDF</button>

Вам необходимо обратиться к обеим библиотекам JS,

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>

Затем вызовите следующую функцию,

//Create PDf from HTML...
function CreatePDFfromHTML() {
    var HTML_Width = $(".content").width();
    var HTML_Height = $(".content").height();
    var top_left_margin = 15;
    var PDF_Width = HTML_Width + (top_left_margin * 2);
    var PDF_Height = (PDF_Width * 1.5) + (top_left_margin * 2);
    var canvas_image_width = HTML_Width;
    var canvas_image_height = HTML_Height;

    var totalPDFPages = Math.ceil(HTML_Height / PDF_Height) - 1;

    html2canvas($(".content")[0]).then(function (canvas) {
        var imgData = canvas.toDataURL("image/jpeg", 1.0);
        var pdf = new jsPDF('p', 'pt', [PDF_Width, PDF_Height]);
        pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, canvas_image_width, canvas_image_height);
        for (var i = 1; i <= totalPDFPages; i++) { 
            pdf.addPage(PDF_Width, PDF_Height);
            pdf.addImage(imgData, 'JPG', top_left_margin, -(PDF_Height*i)+(top_left_margin*4),canvas_image_width,canvas_image_height);
        }
        // if you want to upload pdf on your server
        // you can call ajax request here and pass pdf and upload it.
        pdf.save("{{invoice_name}}.pdf");
        $(".content").hide();
    });
}
Вернуться на верх