From de47a5e8739576dc12d2b59d7be747e9b1cc5e98 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Tue, 31 Aug 2021 20:18:50 +0200 Subject: [PATCH] export PDF avec Flask --- app/scodoc/pe_jurype.py | 16 +++++++------- app/scodoc/pe_view.py | 33 ++++++++++++----------------- app/scodoc/sco_apogee_csv.py | 3 +-- app/scodoc/sco_etape_apogee_view.py | 6 ++---- app/scodoc/sco_trombino.py | 28 +++++++++++++----------- app/scodoc/sco_utils.py | 1 + 6 files changed, 41 insertions(+), 46 deletions(-) diff --git a/app/scodoc/pe_jurype.py b/app/scodoc/pe_jurype.py index ce3a43fdf..5fce90705 100644 --- a/app/scodoc/pe_jurype.py +++ b/app/scodoc/pe_jurype.py @@ -42,12 +42,9 @@ Created on Fri Sep 9 09:15:05 2016 # a l'edition d'un jury de poursuites d'etudes # ---------------------------------------------------------- +import io import os - -from io import StringIO - -from zipfile import ZipFile, BadZipfile -import pprint +from zipfile import ZipFile from app.scodoc.gen_tables import GenTable, SeqGenTable import app.scodoc.sco_utils as scu @@ -169,7 +166,7 @@ class JuryPE(object): # Un zip où ranger les fichiers générés: self.NOM_EXPORT_ZIP = "Jury_PE_%s" % self.diplome - self.zipdata = StringIO() + self.zipdata = io.BytesIO() self.zipfile = ZipFile(self.zipdata, "w") # @@ -206,11 +203,14 @@ class JuryPE(object): # ------------------------------------------------------------------------------------------------------------------ def get_zipped_data(self): - """returns zipped data with all generated (CSV) files""" + """returns file-like data with a zip of all generated (CSV) files. + Reset file cursor at the beginning ! + """ if self.zipfile: self.zipfile.close() self.zipfile = None - return self.zipdata.getvalue() + self.zipdata.seek(0) + return self.zipdata # **************************************************************************************************************** # # Lancement des différentes actions permettant le calcul du jury PE diff --git a/app/scodoc/pe_view.py b/app/scodoc/pe_view.py index 373c36e3d..a8f7007cd 100644 --- a/app/scodoc/pe_view.py +++ b/app/scodoc/pe_view.py @@ -35,6 +35,8 @@ """ +from flask import send_file, request + import app.scodoc.sco_utils as scu from app.scodoc import sco_formsemestre from app.scodoc import html_sco_header @@ -46,7 +48,7 @@ from app.scodoc import pe_jurype from app.scodoc import pe_avislatex -def _pe_view_sem_recap_form(formsemestre_id, REQUEST=None): +def _pe_view_sem_recap_form(formsemestre_id): H = [ html_sco_header.sco_header(page_title="Avis de poursuite d'études"), """

Génération des avis de poursuites d'études

@@ -74,20 +76,15 @@ def _pe_view_sem_recap_form(formsemestre_id, REQUEST=None): return "\n".join(H) + html_sco_header.sco_footer() +# called from the web, POST or GET def pe_view_sem_recap( formsemestre_id, avis_tmpl_file=None, footer_tmpl_file=None, - mode_debug=False, - REQUEST=None, ): - """Génération des avis de poursuite d'étude - - mode_debug = Pour "squeezer" le calcul du jury pe (long) - et debugger uniquement la partie avis latex - """ - if REQUEST and REQUEST.REQUEST_METHOD == "GET": - return _pe_view_sem_recap_form(formsemestre_id, REQUEST=REQUEST) + """Génération des avis de poursuite d'étude""" + if request.method == "GET": + return _pe_view_sem_recap_form(formsemestre_id) prefs = sco_preferences.SemPreferences(formsemestre_id=formsemestre_id) semBase = sco_formsemestre.get_formsemestre(formsemestre_id) @@ -169,14 +166,10 @@ def pe_view_sem_recap( # Ajoute image, LaTeX class file(s) and modeles pe_tools.add_pe_stuff_to_zip(jury.zipfile, jury.NOM_EXPORT_ZIP) data = jury.get_zipped_data() - size = len(data) - content_type = "application/zip" - if REQUEST != None: - REQUEST.RESPONSE.setHeader( - "content-disposition", - 'attachement; filename="%s.zip"' % jury.NOM_EXPORT_ZIP, - ) - REQUEST.RESPONSE.setHeader("content-type", content_type) - REQUEST.RESPONSE.setHeader("content-length", size) - return data + return send_file( + data, + mimetype="application/zip", + download_name=jury.NOM_EXPORT_ZIP + ".zip", + as_attachment=True, + ) diff --git a/app/scodoc/sco_apogee_csv.py b/app/scodoc/sco_apogee_csv.py index c3bf6093d..b23c22154 100644 --- a/app/scodoc/sco_apogee_csv.py +++ b/app/scodoc/sco_apogee_csv.py @@ -1187,7 +1187,6 @@ def export_csv_to_apogee( export_res_modules=True, export_res_sdj=True, export_res_rat=True, - REQUEST=None, ): """Genere un fichier CSV Apogée à partir d'un fichier CSV Apogée vide (ou partiellement rempli) @@ -1306,7 +1305,7 @@ def export_csv_to_apogee( return send_file( data, mimetype="application/zip", - download_name=basename + "-scodoc.zip", + download_name=scu.sanitize_filename(basename + "-scodoc.zip"), as_attachment=True, ) else: diff --git a/app/scodoc/sco_etape_apogee_view.py b/app/scodoc/sco_etape_apogee_view.py index eedb7d9ca..efa9c0074 100644 --- a/app/scodoc/sco_etape_apogee_view.py +++ b/app/scodoc/sco_etape_apogee_view.py @@ -776,7 +776,6 @@ def apo_csv_export_results( block_export_res_ues=False, block_export_res_modules=False, block_export_res_sdj=False, - REQUEST=None, ): """Remplit les fichiers CSV archivés et donne un ZIP avec tous les résultats. @@ -818,7 +817,6 @@ def apo_csv_export_results( export_res_sdj=export_res_sdj, export_res_rat=export_res_rat, dest_zip=dest_zip, - REQUEST=REQUEST, ) dest_zip.close() @@ -829,11 +827,11 @@ def apo_csv_export_results( + "-%s-" % periode + "-".join(etapes_apo) ) - basename = scu.sanitize_filename(scu.unescape_html(basename)) + basename = scu.unescape_html(basename) return send_file( data, mimetype="application/zip", - download_name=basename + ".zip", + download_name=scu.sanitize_filename(basename + ".zip"), as_attachment=True, ) diff --git a/app/scodoc/sco_trombino.py b/app/scodoc/sco_trombino.py index 24019712b..47769baf0 100644 --- a/app/scodoc/sco_trombino.py +++ b/app/scodoc/sco_trombino.py @@ -44,7 +44,7 @@ from reportlab.lib import colors from PIL import Image as PILImage import flask -from flask import url_for, g +from flask import url_for, g, send_file from app import log import app.scodoc.sco_utils as scu @@ -90,7 +90,7 @@ def trombino( return dialog if format == "zip": - return _trombino_zip(groups_infos, REQUEST) + return _trombino_zip(groups_infos) elif format == "pdf": return _trombino_pdf(groups_infos, REQUEST) elif format == "pdflist": @@ -215,7 +215,7 @@ def check_local_photos_availability(groups_infos, REQUEST, format=""): return True, "" -def _trombino_zip(groups_infos, REQUEST): +def _trombino_zip(groups_infos): "Send photos as zip archive" data = io.BytesIO() Z = ZipFile(data, "w") @@ -235,13 +235,13 @@ def _trombino_zip(groups_infos, REQUEST): Z.close() size = data.tell() log("trombino_zip: %d bytes" % size) - content_type = "application/zip" - REQUEST.RESPONSE.setHeader( - "content-disposition", 'attachement; filename="trombi.zip"' + data.seek(0) + return send_file( + data, + mimetype="application/zip", + download_name="trombi.zip", + as_attachment=True, ) - REQUEST.RESPONSE.setHeader("content-type", content_type) - REQUEST.RESPONSE.setHeader("content-length", size) - return data.getvalue() # Copy photos from portal to ScoDoc @@ -384,9 +384,13 @@ def _trombino_pdf(groups_infos, REQUEST): ) ) document.build(objects) - data = report.getvalue() - - return scu.sendPDFFile(REQUEST, data, filename) + report.seek(0) + return send_file( + report, + mimetype=scu.PDF_MIMETYPE, + download_name=scu.sanitize_filename(filename), + as_attachment=True, + ) # --------------------- Sur une idée de l'IUT d'Orléans: diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 9acb31293..bf6a332a9 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -478,6 +478,7 @@ def sanitize_filename(filename): """Keep only valid chars used for archives filenames """ + filename = suppress_accents(filename.replace(" ", "_")) sane = "".join([c for c in filename if c in VALID_CARS_SET]) if len(sane) < 2: sane = time.strftime("%Y-%m-%d-%H%M%S") + "-" + sane