1 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
4 from errno import ENOENT
7 from django.conf import settings
9 from django.http import HttpResponse
10 from wolnelektury.utils import makedirs
12 logger = logging.getLogger(__name__)
15 def render_to_pdf(output_path, template, context=None, add_files=None):
16 """Renders a TeXML document into a PDF file.
18 :param str output_path: is where the PDF file should go
19 :param str template: is a TeXML template path
20 :param context: is context for rendering the template
21 :param dict add_files: a dictionary of additional files XeTeX will need
24 from io import BytesIO
26 from tempfile import mkdtemp
28 import Texml.processor
29 from django.template.loader import render_to_string
31 rendered = render_to_string(template, context)
32 texml = BytesIO(rendered.encode('utf-8'))
33 tempdir = mkdtemp(prefix="render_to_pdf-")
34 tex_path = os.path.join(tempdir, "doc.tex")
35 with open(tex_path, 'wb') as tex_file:
36 Texml.processor.process(texml, tex_file, encoding="utf-8")
39 for add_name, src_file in add_files.items():
40 add_path = os.path.join(tempdir, add_name)
41 if hasattr(src_file, "read"):
42 with open(add_path, 'w') as add_file:
43 add_file.write(add_file.read())
45 shutil.copy(src_file, add_path)
50 subprocess.check_call(
51 ['xelatex', '-interaction=batchmode', tex_path],
52 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
53 makedirs(os.path.dirname(output_path))
54 shutil.move(os.path.join(tempdir, "doc.pdf"), output_path)
57 shutil.rmtree(tempdir)
60 def render_to_csv(output_path, template, context=None, add_files=None):
61 """Renders a TeXML document into a PDF file.
63 :param str output_path: is where the PDF file should go
64 :param str template: is a TeXML template path
65 :param context: is context for rendering the template
66 :param dict add_files: a dictionary of additional files XeTeX will need
69 from django.template.loader import render_to_string
71 makedirs(os.path.dirname(output_path))
73 rendered = render_to_string(template, context)
74 with open(output_path, 'wb') as csv_file:
75 csv_file.write(rendered.encode('utf-8'))
78 def read_chunks(f, size=8192):
85 def generated_file_view(file_name, mime_type, send_name=None, signals=None):
86 file_path = os.path.join(settings.MEDIA_ROOT, file_name)
88 send_name = os.path.basename(file_name)
90 def signal_handler(*args, **kwargs):
94 if oe.errno != ENOENT:
98 for signal in signals:
99 signal.connect(signal_handler, weak=False)
102 def view(request, *args, **kwargs):
103 if not os.path.exists(file_path):
104 func(file_path, *args, **kwargs)
106 if hasattr(send_name, "__call__"):
111 response = HttpResponse(content_type=mime_type)
112 response['Content-Disposition'] = 'attachment; filename=%s' % name
113 with open(file_path, 'rb') as f:
114 for chunk in read_chunks(f):
115 response.write(chunk)