xhtml2pdf 使用波兰语字符转换 html 文件时出现问题
xhtml2pdf problem with converting html file with polish characters
我正在尝试通过创建 html 文件并将其转换为 pdf 然后作为 http 响应发送来制作发票。问题是那些发票包含 UTF-8 不显示的波兰语字符。我曾尝试使用 ISO-8859-2 来显示它们,但我收到错误消息:('charmap' 编解码器无法对位置 1159-1163 中的字符进行编码:字符映射到 )。
utils.py:
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(
src=BytesIO(html.encode('ISO-8859-2')),
dest=result,
encoding='UTF-8'
)
if pdf.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return HttpResponse(result.getvalue(), content_type='application/pdf')
views.py:
class GeneratePDF(View):
def get(self, request, pk=None):
"getting data here"
pdf = render_to_pdf("invoice.html", data)
if pdf:
response = HttpResponse(pdf, content_type='application/pdf')
filename = "Sales_Invoice_%s.pdf" % ("name")
content = "inline; filename=%s" % (filename)
download = request.GET.get("download")
if download:
content = "attachment; filename='%s'" % (filename)
response['Content-Disposition'] = content
return response
return Response(status=rest_status.HTTP_404_NOT_FOUND)
invoice.html:
<html>
<head>
<title>Sales Invoice - {{ sales_invoice.id }}</title>
<style>
@page {
size: A4 portrait;
@frame header_frame {
-pdf-frame-content: header_content;
left: 50pt; width: 512pt; top: 50pt; height: 40pt;
}
@frame content_frame {
left: 50pt; width: 512pt; top: 90pt; height: 632pt;
{% comment %} -pdf-frame-border: 1; {% endcomment %}
}
@frame footer_frame {
-pdf-frame-content: footer_content;
left: 50pt; width: 512pt; top: 772pt; height: 20pt;
}
}
</style>
<head>
<body>
<div id="header_content"><h1>Sales Invoice {{ sales_invoice.id }}</h1></div>
<p>
<strong>Date of issue:</strong> Krakow, {{ today | date:"d/m/Y" }}<br />
<strong>Date of sale:</strong> {{ today | date:"d/m/Y" }}<br />
<strong>Date of payment:</strong> {{ today | date:"d/m/Y" }}<br />
<strong>Payment:</strong> cash<br />
</p>
{% if sales_invoice.parts %}
<table id="cssTable" class="cssTdTh">
<thead>
<tr>
<th>Part</th>
<th>Code</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{% for part in sales_invoice.parts %}
<tr>
<td>{{ part.name }}</td>
<td>{{ part.code }}</td>
<td>{{ part.amount }}</td>
<td>{{ part.price_out }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="3">Total</td>
<td>{{sales_invoice.total_part_price}}</td>
</tr>
</tbody>
</table>
{% endif %}
<br />
{% if sales_invoice.works %}
<table id="cssTable" class="cssTdTh">
<thead>
<tr>
<th>Work</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{% for work in sales_invoice.works %}
<tr>
<td>{{ work.name }}</td>
<td>{{ work.price }}</td>
</tr>
{% endfor %}
<td>Total</td>
<td>{{sales_invoice.total_work_price}}</td>
</tbody>
</table>
{% endif %}
<div id="footer_content">Footer</div>
</body>
</html>
print("==============================================================")
for work in sales_invoice.works.all():
print(work.name)
for part in sales_invoice.parts.all():
print(part.name)
print("==============================================================")
output:
==============================================================
Wymiana łącznika elastycznego
Wymiana sprężarki klimatyzacji
Montaż radia
==============================================================
Bęben
Bagnet
Alternator
==============================================================
我得到的结果:
使用 ISO-8859-2:result
使用 UTF-8:result
点冻结:
Django==3.2.7
xhtml2pdf==0.2.5
问题不在于编码,而在于字体。解决方案是使用 mhtml2pdf 支持的亚洲字体。 xhtml2pdf documentation
比如客户的名字可以有波兰字母,所以我这里就用这个字体
<td style="font-family: STSong-Light">{{client.full_name}}</td>
utils.py:
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(
src=BytesIO(html.encode('UTF-8')),
dest=result,
encoding='UTF-8'
)
if pdf.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return HttpResponse(result.getvalue(), content_type='application/pdf')
我正在尝试通过创建 html 文件并将其转换为 pdf 然后作为 http 响应发送来制作发票。问题是那些发票包含 UTF-8 不显示的波兰语字符。我曾尝试使用 ISO-8859-2 来显示它们,但我收到错误消息:('charmap' 编解码器无法对位置 1159-1163 中的字符进行编码:字符映射到 )。
utils.py:
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(
src=BytesIO(html.encode('ISO-8859-2')),
dest=result,
encoding='UTF-8'
)
if pdf.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return HttpResponse(result.getvalue(), content_type='application/pdf')
views.py:
class GeneratePDF(View):
def get(self, request, pk=None):
"getting data here"
pdf = render_to_pdf("invoice.html", data)
if pdf:
response = HttpResponse(pdf, content_type='application/pdf')
filename = "Sales_Invoice_%s.pdf" % ("name")
content = "inline; filename=%s" % (filename)
download = request.GET.get("download")
if download:
content = "attachment; filename='%s'" % (filename)
response['Content-Disposition'] = content
return response
return Response(status=rest_status.HTTP_404_NOT_FOUND)
invoice.html:
<html>
<head>
<title>Sales Invoice - {{ sales_invoice.id }}</title>
<style>
@page {
size: A4 portrait;
@frame header_frame {
-pdf-frame-content: header_content;
left: 50pt; width: 512pt; top: 50pt; height: 40pt;
}
@frame content_frame {
left: 50pt; width: 512pt; top: 90pt; height: 632pt;
{% comment %} -pdf-frame-border: 1; {% endcomment %}
}
@frame footer_frame {
-pdf-frame-content: footer_content;
left: 50pt; width: 512pt; top: 772pt; height: 20pt;
}
}
</style>
<head>
<body>
<div id="header_content"><h1>Sales Invoice {{ sales_invoice.id }}</h1></div>
<p>
<strong>Date of issue:</strong> Krakow, {{ today | date:"d/m/Y" }}<br />
<strong>Date of sale:</strong> {{ today | date:"d/m/Y" }}<br />
<strong>Date of payment:</strong> {{ today | date:"d/m/Y" }}<br />
<strong>Payment:</strong> cash<br />
</p>
{% if sales_invoice.parts %}
<table id="cssTable" class="cssTdTh">
<thead>
<tr>
<th>Part</th>
<th>Code</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{% for part in sales_invoice.parts %}
<tr>
<td>{{ part.name }}</td>
<td>{{ part.code }}</td>
<td>{{ part.amount }}</td>
<td>{{ part.price_out }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="3">Total</td>
<td>{{sales_invoice.total_part_price}}</td>
</tr>
</tbody>
</table>
{% endif %}
<br />
{% if sales_invoice.works %}
<table id="cssTable" class="cssTdTh">
<thead>
<tr>
<th>Work</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{% for work in sales_invoice.works %}
<tr>
<td>{{ work.name }}</td>
<td>{{ work.price }}</td>
</tr>
{% endfor %}
<td>Total</td>
<td>{{sales_invoice.total_work_price}}</td>
</tbody>
</table>
{% endif %}
<div id="footer_content">Footer</div>
</body>
</html>
print("==============================================================")
for work in sales_invoice.works.all():
print(work.name)
for part in sales_invoice.parts.all():
print(part.name)
print("==============================================================")
output:
==============================================================
Wymiana łącznika elastycznego
Wymiana sprężarki klimatyzacji
Montaż radia
==============================================================
Bęben
Bagnet
Alternator
==============================================================
我得到的结果:
使用 ISO-8859-2:result
使用 UTF-8:result
点冻结:
Django==3.2.7
xhtml2pdf==0.2.5
问题不在于编码,而在于字体。解决方案是使用 mhtml2pdf 支持的亚洲字体。 xhtml2pdf documentation
比如客户的名字可以有波兰字母,所以我这里就用这个字体
<td style="font-family: STSong-Light">{{client.full_name}}</td>
utils.py:
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(
src=BytesIO(html.encode('UTF-8')),
dest=result,
encoding='UTF-8'
)
if pdf.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return HttpResponse(result.getvalue(), content_type='application/pdf')