-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
96 lines (78 loc) · 3.38 KB
/
app.py
File metadata and controls
96 lines (78 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
from flask import Flask, render_template, make_response, url_for
from weasyprint import HTML, CSS
import io
app = Flask(__name__)
@app.route('/')
def index():
return 'WeasyPrint PDF prototype. Use /report to get a PDF.'
@app.route('/report')
def report():
# Example data for the template
data = {
'title': 'Sample Report',
'items': [
{'name': 'Apples', 'qty': 10, 'price': 0.5},
{'name': 'Bananas', 'qty': 5, 'price': 0.3},
{'name': 'Oranges', 'qty': 8, 'price': 0.4},
],
# sections used for the TOC (title and anchor)
'sections': [
{'id': 'section-items', 'title': 'Items'},
{'id': 'section-long', 'title': 'Long Content'},
],
# long content to force multiple pages
'long_text': '\n\n'.join([('This is a long paragraph intended to demonstrate page breaks and multi-page output. ' \
'It repeats to create a sizeable block of text. ' * 4) for _ in range(60)])
}
html = render_template('report.html', **data)
# Build a file:// base_url so WeasyPrint can load static assets directly from the container filesystem
import pathlib
base_path = pathlib.Path(app.root_path).as_uri()
base_url = base_path + '/'
try:
pdf_io = io.BytesIO()
css_path = str(pathlib.Path(app.root_path) / 'static' / 'css' / 'report.css')
HTML(string=html, base_url=base_url).write_pdf(target=pdf_io, stylesheets=[CSS(filename=css_path)])
pdf_io.seek(0)
response = make_response(pdf_io.read())
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = 'inline; filename=report.pdf'
return response
except Exception as e:
app.logger.exception('PDF generation failed')
return (f'PDF generation error: {e}', 500)
@app.route('/report-timing')
def report_timing():
"""Render the PDF server-side but only return the elapsed rendering time in milliseconds.
This helps measure raw server rendering time without transferring the PDF bytes back to client."""
from flask import request
pages = int(request.args.get('pages', '3'))
paras_per_page = 8
total_paras = max(1, pages * paras_per_page)
data = {
'title': 'Sample Report',
'items': [
{'name': 'Apples', 'qty': 10, 'price': 0.5},
{'name': 'Bananas', 'qty': 5, 'price': 0.3},
{'name': 'Oranges', 'qty': 8, 'price': 0.4},
],
'sections': [
{'id': 'section-items', 'title': 'Items'},
{'id': 'section-long', 'title': 'Long Content'},
{'id': 'section-images', 'title': 'Images'},
],
'long_text': '\n\n'.join([('This is paragraph %d. ' % (i+1)) + ('Long content. ' * 10) for i in range(total_paras)])
}
html = render_template('report.html', **data)
import time, pathlib
base_path = pathlib.Path(app.root_path).as_uri()
base_url = base_path + '/'
css_path = str(pathlib.Path(app.root_path) / 'static' / 'css' / 'report.css')
start = time.perf_counter()
pdf_io = io.BytesIO()
HTML(string=html, base_url=base_url).write_pdf(target=pdf_io, stylesheets=[CSS(filename=css_path)])
end = time.perf_counter()
elapsed_ms = int((end - start) * 1000)
return {'elapsed_ms': elapsed_ms}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)