Anonymous
Сгенерировать HTML для PDF с использованием xhtml2pdf в проекте Django
Сообщение
Anonymous » 11 фев 2025, 01:01
У меня есть HTML -страница, содержащая несколько таблиц. При преобразовании в PDF с использованием xhtml2pdf он работает нормально, если расширено только несколько таблиц. Однако, если я расширяю больше таблиц, я сталкиваюсь с ограничением размера, где PDF оказывается пустым, если содержание превышает определенный размер (30 МБ).
views.py < Br /> Код: Выделить всё
def generate_pdf(request):
template_path = 'app.html'
context = {
'data': 'This is dynamic data passed to the template'
}
pdf_stylesheets = """
@page {
size: A4 landscape;
margin: 1.5cm;
}
.table-wrapper {
width: 100%;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed !important;
}
thead {
display: table-header-group;
}
tbody {
page-break-inside: avoid !important;
break-inside: avoid !important;
}
tr {
page-break-inside: avoid !important;
break-inside: avoid !important;
}
td {
padding: 8px;
border: 1px solid #ddd;
font-size: 14px;
vertical-align: top;
}
/* Column widths */
td:nth-child(1) { width: 10%; }
td:nth-child(2) { width: 15%; }
td:nth-child(3) { width: 10%; }
td:nth-child(4) {
width: 45%;
max-width: 45%;
word-wrap: break-word !important;
word-break: break-word !important;
overflow-wrap: break-word !important;
white-space: pre-wrap !important;
}
td:nth-child(5) { width: 20%; }
.message-cell {
position: relative;
max-width: 45%;
word-wrap: break-word !important;
word-break: break-word !important;
overflow-wrap: break-word !important;
white-space: pre-wrap !important;
}
.message-content {
display: inline-block;
width: 100%;
word-wrap: break-word !important;
word-break: break-word !important;
overflow-wrap: break-word !important;
white-space: pre-wrap !important;
line-height: 1.4;
}
th {
padding: 8px;
background-color: #355b7a;
color: white;
border: 1px solid #ddd;
font-size: 14px;
}
@media print {
table {
table-layout: fixed !important;
}
thead {
display: table-header-group !important;
}
tbody {
page-break-inside: avoid !important;
break-inside: avoid !important;
display: block !important;
min-height: fit-content !important;
}
tr {
page-break-inside: avoid !important;
break-inside: avoid !important;
}
td {
border: 0.5pt solid #ddd !important;
font-size: 14px !important;
}
.message-cell, .message-content {
page-break-inside: avoid !important;
break-inside: avoid !important;
}
* {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
}
"""
html = render_to_string(template_path, context)
html = pdf_stylesheets + html
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="app.pdf"'
pdf_options = {
'page-size': 'A4',
'orientation': 'Landscape',
'margin-top': '1.5cm',
'margin-right': '1.5cm',
'margin-bottom': '1.5cm',
'margin-left': '1.5cm',
'encoding': 'UTF-8',
'keep-with-next': 'true',
'no-split-tables': 'true',
'enable-smart-shrinking': 'true',
'print-media-type': 'true'
}
pisa_status = pisa.CreatePDF(
html.encode('UTF-8'),
dest=response,
encoding='UTF-8',
show_error_as_pdf=True,
pdf_options=pdf_options
)
if pisa_status.err:
return HttpResponse('We had some errors
' + html + '')
return response
< /code>
шаблон HTML < /p>
{% load static %}
Test Report
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.container {
display: flex;
flex-direction: column;
align-items: left;
margin: 0;
padding: 0;
}
.header-content {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 0;
padding: 0;
}
h1 {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 1.5em;
}
.environment-details {
align-self: flex-start;
color: black;
font-size: 0.9em;
}
header {
background: #5ea3db;
color: white;
padding-top: 10px;
min-height: 60px;
border-bottom: #e8491d 3px solid;
}
.header-buttons {
position: absolute;
top: 2%;
right: 0;
transform: translateY(-50%);
display: flex;
gap: 3px;
}
.header-buttons button {
border: none;
border-radius: 7px;
padding: 5px 10px;
font-size: 14px;
transition-duration: 0.4s;
cursor: pointer;
}
.table-container {
width: 95%;
margin: 20px auto;
background: white;
padding: 15px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.4);
}
.table-wrapper {
width: auto;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin-bottom: 15px;
page-break-inside: avoid;
overflow: visible;
}
.main_table {
min-width: 100%;
margin-bottom: 15px;
}
.main_table th {
background-color: #355b7a;
color: white;
font-size: 0.9em;
white-space: nowrap;
padding: 8px 15px;
position: sticky;
top: 0;
}
.main_table td {
padding: 8px 15px;
text-align: justify;
font-size: 0.8em;
white-space: nowrap;
}
.main_table td:nth-child(1) {
width: 40%;
word-break: break-word;
white-space: normal;
overflow-wrap: break-word;
}
.main_table td:nth-child(2) { width: 10%; }
.main_table td:nth-child(3) { width: 15%; }
.main_table td:nth-child(4) { width: 15%; }
.main_table td:nth-child(5) {
width: 20%;
word-break: break-word;
white-space: normal;
overflow-wrap: break-word;
}
.summary_table td {
padding: 15px;
font-size: 0.8em;
}
table {
border-collapse: collapse;
background-color: white;
}
table, th, td {
border: 1px solid #ddd;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
.table-wrapper::-webkit-scrollbar {
height: 8px;
}
.table-wrapper::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
.table-wrapper::-webkit-scrollbar-thumb {
background: #888;
border-radius: 4px;
}
.table-wrapper::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* @media print {
body { zoom: 0.75; }
} */
@media print {
body {
margin: 0;
padding: 0;
}
.page-break {
page-break-before: always;
}
table, img {
page-break-inside: avoid;
}
}
TEST REPORT
Project Name:[/b] {{ project_name }}[b]
Environment:[/b] {{environment}}[b]
Verification Type:[/b] {{VERIFICATION_TYPE}}
{% if log_file_name %}
[url={{ log_file_name }}]Robot Log[/url]
{% else %}
Robot Log Not Available
{% endif %}
Download PDF
This report includes the test case details and individual summary tables for each test case.
{{ main_table_html|safe }}
{% for table in summary_tables_html %}
{{ table|safe }}
{% endfor %}
const script = document.createElement('script');
script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js";
script.onload = function () {
document.getElementById('downloadBtn').addEventListener('click', function() {
// Temporarily remove collapsed tables
document.querySelectorAll('details:not([open])').forEach(detail => {
detail.style.display = 'none';
});
const element = document.body;
const opt = {
margin: [0.2, 0.2, 0.2, 0.2],
filename: 'test_report.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 4, scrollX: 0, scrollY: 0, useCORS: true },
jsPDF: { unit: 'in', format: 'a4', orientation: 'landscape' }
};
// Generate and estimate PDF size before downloading
html2pdf().from(element).set(opt).toPdf().output('datauristring').then(dataUri => {
let estimatedSizeKB = (dataUri.length * (3 / 4)) / 1024; // Convert Base64 size to KB
console.log("PDF Size (KB):", estimatedSizeKB);
// If the estimated size is too large, show an alert and stop the process
if (estimatedSizeKB >= 100 && estimatedSizeKB {
detail.style.display = '';
});
return; // Stop execution, do NOT generate the PDF
}
// If the size is acceptable, proceed with the download
html2pdf().from(element).set(opt).save().then(() => {
// Restore hidden elements after generating the PDF
document.querySelectorAll('details').forEach(detail => {
detail.style.display = '';
});
});
});
});
};
document.head.appendChild(script);
Как я могу гарантировать, что большие PDF -файлы загружаются правильно?
Подробнее здесь:
https://stackoverflow.com/questions/794 ... go-project
1739224864
Anonymous
У меня есть HTML -страница, содержащая несколько таблиц. При преобразовании в PDF с использованием xhtml2pdf он работает нормально, если расширено только несколько таблиц. Однако, если я расширяю больше таблиц, я сталкиваюсь с ограничением размера, где PDF оказывается пустым, если содержание превышает определенный размер (30 МБ). [b] views.py < Br />[code]def generate_pdf(request): template_path = 'app.html' context = { 'data': 'This is dynamic data passed to the template' } pdf_stylesheets = """ @page { size: A4 landscape; margin: 1.5cm; } .table-wrapper { width: 100%; } table { width: 100%; border-collapse: collapse; table-layout: fixed !important; } thead { display: table-header-group; } tbody { page-break-inside: avoid !important; break-inside: avoid !important; } tr { page-break-inside: avoid !important; break-inside: avoid !important; } td { padding: 8px; border: 1px solid #ddd; font-size: 14px; vertical-align: top; } /* Column widths */ td:nth-child(1) { width: 10%; } td:nth-child(2) { width: 15%; } td:nth-child(3) { width: 10%; } td:nth-child(4) { width: 45%; max-width: 45%; word-wrap: break-word !important; word-break: break-word !important; overflow-wrap: break-word !important; white-space: pre-wrap !important; } td:nth-child(5) { width: 20%; } .message-cell { position: relative; max-width: 45%; word-wrap: break-word !important; word-break: break-word !important; overflow-wrap: break-word !important; white-space: pre-wrap !important; } .message-content { display: inline-block; width: 100%; word-wrap: break-word !important; word-break: break-word !important; overflow-wrap: break-word !important; white-space: pre-wrap !important; line-height: 1.4; } th { padding: 8px; background-color: #355b7a; color: white; border: 1px solid #ddd; font-size: 14px; } @media print { table { table-layout: fixed !important; } thead { display: table-header-group !important; } tbody { page-break-inside: avoid !important; break-inside: avoid !important; display: block !important; min-height: fit-content !important; } tr { page-break-inside: avoid !important; break-inside: avoid !important; } td { border: 0.5pt solid #ddd !important; font-size: 14px !important; } .message-cell, .message-content { page-break-inside: avoid !important; break-inside: avoid !important; } * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; } } """ html = render_to_string(template_path, context) html = pdf_stylesheets + html response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="app.pdf"' pdf_options = { 'page-size': 'A4', 'orientation': 'Landscape', 'margin-top': '1.5cm', 'margin-right': '1.5cm', 'margin-bottom': '1.5cm', 'margin-left': '1.5cm', 'encoding': 'UTF-8', 'keep-with-next': 'true', 'no-split-tables': 'true', 'enable-smart-shrinking': 'true', 'print-media-type': 'true' } pisa_status = pisa.CreatePDF( html.encode('UTF-8'), dest=response, encoding='UTF-8', show_error_as_pdf=True, pdf_options=pdf_options ) if pisa_status.err: return HttpResponse('We had some errors ' + html + '') return response < /code> шаблон HTML < /p> {% load static %} Test Report body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f5f5f5; } .container { display: flex; flex-direction: column; align-items: left; margin: 0; padding: 0; } .header-content { width: 100%; display: flex; flex-direction: row; justify-content: space-between; margin: 0; padding: 0; } h1 { position: absolute; left: 50%; transform: translateX(-50%); font-size: 1.5em; } .environment-details { align-self: flex-start; color: black; font-size: 0.9em; } header { background: #5ea3db; color: white; padding-top: 10px; min-height: 60px; border-bottom: #e8491d 3px solid; } .header-buttons { position: absolute; top: 2%; right: 0; transform: translateY(-50%); display: flex; gap: 3px; } .header-buttons button { border: none; border-radius: 7px; padding: 5px 10px; font-size: 14px; transition-duration: 0.4s; cursor: pointer; } .table-container { width: 95%; margin: 20px auto; background: white; padding: 15px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.4); } .table-wrapper { width: auto; overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 15px; page-break-inside: avoid; overflow: visible; } .main_table { min-width: 100%; margin-bottom: 15px; } .main_table th { background-color: #355b7a; color: white; font-size: 0.9em; white-space: nowrap; padding: 8px 15px; position: sticky; top: 0; } .main_table td { padding: 8px 15px; text-align: justify; font-size: 0.8em; white-space: nowrap; } .main_table td:nth-child(1) { width: 40%; word-break: break-word; white-space: normal; overflow-wrap: break-word; } .main_table td:nth-child(2) { width: 10%; } .main_table td:nth-child(3) { width: 15%; } .main_table td:nth-child(4) { width: 15%; } .main_table td:nth-child(5) { width: 20%; word-break: break-word; white-space: normal; overflow-wrap: break-word; } .summary_table td { padding: 15px; font-size: 0.8em; } table { border-collapse: collapse; background-color: white; } table, th, td { border: 1px solid #ddd; } tr:nth-child(even) { background-color: #f2f2f2; } .table-wrapper::-webkit-scrollbar { height: 8px; } .table-wrapper::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 4px; } .table-wrapper::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; } .table-wrapper::-webkit-scrollbar-thumb:hover { background: #555; } /* @media print { body { zoom: 0.75; } } */ @media print { body { margin: 0; padding: 0; } .page-break { page-break-before: always; } table, img { page-break-inside: avoid; } } TEST REPORT Project Name:[/b] {{ project_name }}[b] Environment:[/b] {{environment}}[b] Verification Type:[/b] {{VERIFICATION_TYPE}} {% if log_file_name %} [url={{ log_file_name }}]Robot Log[/url] {% else %} Robot Log Not Available {% endif %} Download PDF This report includes the test case details and individual summary tables for each test case. {{ main_table_html|safe }} {% for table in summary_tables_html %} {{ table|safe }} {% endfor %} const script = document.createElement('script'); script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"; script.onload = function () { document.getElementById('downloadBtn').addEventListener('click', function() { // Temporarily remove collapsed tables document.querySelectorAll('details:not([open])').forEach(detail => { detail.style.display = 'none'; }); const element = document.body; const opt = { margin: [0.2, 0.2, 0.2, 0.2], filename: 'test_report.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 4, scrollX: 0, scrollY: 0, useCORS: true }, jsPDF: { unit: 'in', format: 'a4', orientation: 'landscape' } }; // Generate and estimate PDF size before downloading html2pdf().from(element).set(opt).toPdf().output('datauristring').then(dataUri => { let estimatedSizeKB = (dataUri.length * (3 / 4)) / 1024; // Convert Base64 size to KB console.log("PDF Size (KB):", estimatedSizeKB); // If the estimated size is too large, show an alert and stop the process if (estimatedSizeKB >= 100 && estimatedSizeKB { detail.style.display = ''; }); return; // Stop execution, do NOT generate the PDF } // If the size is acceptable, proceed with the download html2pdf().from(element).set(opt).save().then(() => { // Restore hidden elements after generating the PDF document.querySelectorAll('details').forEach(detail => { detail.style.display = ''; }); }); }); }); }; document.head.appendChild(script); [/code] Как я могу гарантировать, что большие PDF -файлы загружаются правильно? Подробнее здесь: [url]https://stackoverflow.com/questions/79428390/generate-html-to-pdf-using-xhtml2pdf-in-django-project[/url]