diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2022-05-16 18:28:37 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2022-07-08 09:58:50 +0200 |
commit | 462d84cf5a8787b55fb31d6012b5b496e52190df (patch) | |
tree | 516d4c8fd2a97bef665b37b7d71149988d2947d7 | |
parent | 03df2dd4e3f21f8e134d0d6cd70b05401872a2ef (diff) | |
download | Ishtar-462d84cf5a8787b55fb31d6012b5b496e52190df.tar.bz2 Ishtar-462d84cf5a8787b55fb31d6012b5b496e52190df.zip |
Generate preview image for PDF
-rw-r--r-- | CHANGES-DEV.md | 5 | ||||
-rw-r--r-- | example_project/settings.py | 1 | ||||
-rw-r--r-- | ishtar_common/forms_common.py | 2 | ||||
-rw-r--r-- | ishtar_common/models.py | 10 | ||||
-rw-r--r-- | ishtar_common/tests.py | 18 | ||||
-rw-r--r-- | ishtar_common/utils.py | 45 |
6 files changed, 77 insertions, 4 deletions
diff --git a/CHANGES-DEV.md b/CHANGES-DEV.md index b5807eeb4..0d21815f1 100644 --- a/CHANGES-DEV.md +++ b/CHANGES-DEV.md @@ -25,12 +25,13 @@ Ishtar develop changelog - Search: - document: operation year, operation type - context record - by operation name -- commands: +- Commands: - ishtar_maintenance_task: fix operation missing parcels - Tables: - operation - scientific column -Sheet: +- Sheet: - organization: sort member by alphabetic +- Generate preview image for PDF ### Bugs ### diff --git a/example_project/settings.py b/example_project/settings.py index acf127121..53f15cc38 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -294,6 +294,7 @@ MAX_UPLOAD_SIZE = 100 # in Mo # path to the "dot" program to generate graph DOT_BINARY = "/usr/bin/dot" +PDFTOPPM_BINARY = "" TEST_RUNNER = "ishtar_common.tests.ManagedModelTestRunner" SELENIUM_TEST = False diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 572c1b70a..57efa72cd 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -1716,7 +1716,7 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType): def clean_source_page_range(self): value = self.cleaned_data.get("source_page_range", None).replace(" ", "") - if value and not re.match(r"^(\d+[-;]*\d)+$", value): + if value and not re.match(r"^(\d+[-;]*\d*)+$", value): raise forms.ValidationError(_("Incorrect page range.")) return value diff --git a/ishtar_common/models.py b/ishtar_common/models.py index c46aad6c1..a133afead 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -81,6 +81,7 @@ from ishtar_common.utils import ( get_image_path, serialize_args_for_tasks, task, + generate_pdf_preview, ) from ishtar_common.utils_secretary import IshtarSecretaryRenderer @@ -4615,7 +4616,14 @@ class Document( self.save(no_path_change=True) -post_save.connect(cached_label_changed, sender=Document) +def document_changed(sender, **kwargs): + cached_label_changed(sender, **kwargs) + if not settings.PDFTOPPM_BINARY or not kwargs.get("instance"): + return + generate_pdf_preview(kwargs.get("instance")) + + +post_save.connect(document_changed, sender=Document) class OperationType(GeneralType): diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index 6b200ef39..0c790bdd5 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -3656,6 +3656,24 @@ class DocumentTest(TestCase): doc.operations.add(self.ope1) self.assertEqual(doc.operations.count(), 0) + def test_generate_pdftoppm(self): + if not settings.PDFTOPPM_BINARY: + return + pdf_path = os.path.join( + settings.ROOT_PATH, "..", "ishtar_common", "tests", "simple.pdf" + ) + doc = models.Document.objects.create( + title="Document", + associated_file=SimpleUploadedFile( + name="simple.pdf", + content=open(pdf_path, "rb").read(), + content_type="application/pdf", + ) + ) + doc.operations.add(self.ope1) + doc = models.Document.objects.get(id=doc.pk) + self.assertTrue(doc.image.path) + def test_create_with_parent(self): doc = models.Document.objects.create(title="Parent document") doc.operations.add(self.ope1) diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 173338b4f..bfb5d0e32 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -2117,3 +2117,48 @@ class IshtarFileSystemStorage(FileSystemStorage): if not os.path.exists(os.readlink(path_name)): os.remove(path_name) return os.path.exists(path_name) + + +def generate_pdf_preview(item, save=True, tempdir=None, page_number=None): + if not settings.PDFTOPPM_BINARY: + return + preview_tmp_name = None + if not item.image and item.source and item.source_page_range: + tempdir = tempfile.mkdtemp("-ishtarppmtopdf") + try: + page_number = int( + item.source_page_range.split("-")[0].split(";")[0].split(",")[0]) + except ValueError: + page_number = 1 + returned = generate_pdf_preview(item.source, save=False, tempdir=tempdir, + page_number=page_number) + if not returned: + return + tempdir, preview_tmp_name = returned + elif (not page_number and item.image) \ + or not item.associated_file \ + or not item.associated_file.path \ + or not item.associated_file.path.lower().endswith(".pdf"): + return + if not page_number: + page_number = 1 + + if not tempdir: + tempdir = tempfile.mkdtemp("-ishtarppmtopdf") + if not preview_tmp_name: + preview_tmp_name = tempdir + os.path.sep + "preview" + args = (settings.PDFTOPPM_BINARY, "-singlefile", "-jpeg", "-f", str(page_number), + item.associated_file.path, preview_tmp_name) + + try: + popen = subprocess.Popen(args) + popen.wait(timeout=5) + except subprocess.SubprocessError: + return + if not save: + return tempdir, preview_tmp_name + + with open(preview_tmp_name + ".jpg", "rb") as preview: + django_file = File(preview) + getattr(item, "image").save("page.jpg", django_file, save=True) + shutil.rmtree(tempdir) |