diff --git a/partitioncloud/modules/albums.py b/partitioncloud/modules/albums.py index 185ab18..1aa3775 100644 --- a/partitioncloud/modules/albums.py +++ b/partitioncloud/modules/albums.py @@ -5,12 +5,12 @@ Albums module import os import pypdf import shutil - from uuid import uuid4 from typing import TypeVar from flask import (Blueprint, abort, flash, redirect, render_template, - request, session, current_app) + request, session, current_app, send_file, g, url_for) +from werkzeug.utils import secure_filename from flask_babel import _ from .auth import login_required @@ -115,6 +115,30 @@ def qr_code(uuid): return utils.get_qrcode(f"/albums/{uuid}") +@bp.route("//zip") +def zip_download(uuid): + """ + Télécharger un album comme fichier zip + """ + if g.user is None and current_app.config["ZIP_REQUIRE_LOGIN"]: + flash(_("You need to login to access this resource.")) + return redirect(url_for("auth.login")) + + try: + album = Album(uuid=uuid) + except LookupError: + try: + album = Album(uuid=utils.format_uuid(uuid)) + return redirect(f"/albums/{utils.format_uuid(uuid)}") + except LookupError: + return abort(404) + + return send_file( + album.to_zip(current_app.instance_path), + download_name=secure_filename(f"{album.name}.zip") + ) + + @bp.route("/create-album", methods=["POST"]) @login_required def create_album_req(): diff --git a/partitioncloud/modules/classes/album.py b/partitioncloud/modules/classes/album.py index 441d95d..e9f5232 100644 --- a/partitioncloud/modules/classes/album.py +++ b/partitioncloud/modules/classes/album.py @@ -2,6 +2,10 @@ Classe Album """ import os +import io +import zipfile + +from werkzeug.utils import secure_filename from ..db import get_db from ..utils import new_uuid @@ -165,6 +169,23 @@ class Album(): ) db.commit() + + def to_zip(self, instance_path): + data = io.BytesIO() + with zipfile.ZipFile(data, mode="w") as z: + for partition in self.get_partitions(): + z.write(os.path.join( + instance_path, + "partitions", + f"{partition['uuid']}.pdf" + ), arcname=secure_filename(partition['name']+".pdf") + ) + + # Spooling back to the beginning of the buffer + data.seek(0) + + return data + def create(name: str) -> str: """Créer un nouvel album""" diff --git a/partitioncloud/modules/classes/groupe.py b/partitioncloud/modules/classes/groupe.py index 1ba9301..f4390b0 100644 --- a/partitioncloud/modules/classes/groupe.py +++ b/partitioncloud/modules/classes/groupe.py @@ -1,3 +1,12 @@ +""" +Classe Groupe +""" +import io +import os +import zipfile + +from werkzeug.utils import secure_filename + from ..db import get_db from .album import Album @@ -116,3 +125,21 @@ class Groupe(): (self.id,) ).fetchall() return [i["id"] for i in data] + + def to_zip(self, instance_path): + data = io.BytesIO() + with zipfile.ZipFile(data, mode="w") as z: + for album in self.get_albums(): + for partition in album.get_partitions(): + z.write(os.path.join( + instance_path, + "partitions", + f"{partition['uuid']}.pdf" + ), arcname=secure_filename(album.name)+"/" + +secure_filename(partition['name']+".pdf") + ) + + # Spooling back to the beginning of the buffer + data.seek(0) + + return data \ No newline at end of file diff --git a/partitioncloud/modules/groupe.py b/partitioncloud/modules/groupe.py index 92bcd2d..59cdb44 100644 --- a/partitioncloud/modules/groupe.py +++ b/partitioncloud/modules/groupe.py @@ -3,7 +3,8 @@ Groupe module """ from flask import (Blueprint, abort, flash, redirect, render_template, - request, session, current_app) + request, session, current_app, send_file, g, url_for) +from werkzeug.utils import secure_filename from flask_babel import _ from .auth import login_required @@ -261,6 +262,31 @@ def get_album(groupe_uuid, album_uuid): ) +@bp.route("//zip") +def zip_download(groupe_uuid): + """ + Télécharger un groupe comme fichier zip + """ + if g.user is None and current_app.config["ZIP_REQUIRE_LOGIN"]: + flash(_("You need to login to access this resource.")) + return redirect(url_for("auth.login")) + + try: + groupe = Groupe(uuid=groupe_uuid) + except LookupError: + try: + groupe = Groupe(uuid=utils.format_uuid(groupe_uuid)) + return redirect(f"/groupe/{utils.format_uuid(groupe_uuid)}/zip") + except LookupError: + return abort(404) + + + return send_file( + groupe.to_zip(current_app.instance_path), + download_name=secure_filename(f"{groupe.name}.zip") + ) + + @bp.route("///qr") def groupe_qr_code(groupe_uuid, album_uuid): return utils.get_qrcode(f"/groupe/{groupe_uuid}/{album_uuid}")