Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 8 additions & 19 deletions geonode/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
import math
import uuid
import logging
import tempfile
import traceback
from io import BytesIO
from typing import List, Optional, Union, Tuple
from sequences.models import Sequence
from sequences import get_next_value
Expand All @@ -37,7 +39,7 @@
from django.db.models import Q, signals
from django.db.utils import IntegrityError, OperationalError
from django.contrib.auth.models import Group
from django.core.files.base import ContentFile
from django.core.files import File
from django.contrib.auth import get_user_model
from django.db.models.query import QuerySet
from django.db.models.fields.json import JSONField
Expand Down Expand Up @@ -1593,28 +1595,15 @@ def save_thumbnail(self, filename, image, thumbnail_algorithm=ThumbnailAlgorithm
image = None

if image:
actual_name = storage_manager.save(upload_path, ContentFile(image))
actual_file_name = os.path.basename(actual_name)

if filename != actual_file_name:
upload_path = upload_path.replace(filename, actual_file_name)
url = storage_manager.url(upload_path)
try:
# Optimize the Thumbnail size and resolution
im = Image.open(storage_manager.open(actual_name))
im = Image.open(BytesIO(image))
im = thumbnail_algorithm(im, **kwargs)

# Saving the thumb into a temporary directory on file system
tmp_location = os.path.abspath(f"{settings.MEDIA_ROOT}/{upload_path}")
im.save(tmp_location, quality="high")

with open(tmp_location, "rb+") as img:
# Saving the img via storage manager
storage_manager.save(upload_path, img)

# If we use a remote storage, the local img is deleted
if tmp_location != storage_manager.path(upload_path):
os.remove(tmp_location)
with tempfile.NamedTemporaryFile(suffix=".jpg") as optimized_tmp:
im.save(optimized_tmp, format="JPEG", quality="high")
optimized_tmp.seek(0)
storage_manager.save(upload_path, File(optimized_tmp))
except Exception as e:
logger.exception(e)

Expand Down
29 changes: 29 additions & 0 deletions geonode/base/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,35 @@ def test_thumb_utils_methods(self, image):
thumb_utils.remove_thumbs(filename)
self.assertFalse(thumb_utils.thumb_exists(filename))

def test_save_thumbnail_creates_a_single_file(self):
"""
A single save_thumbnail call must create exactly one thumbnail file
"""
image = Image.new("RGB", (100, 100))
for x in range(100):
image.putpixel((x, x), (x + 1, (x * 2) % 256, (x * 3) % 256))
with BytesIO() as output:
image.save(output, format="PNG")
content = output.getvalue()

name_prefix = f"dataset-{self.rb.uuid}-thumb"
thumbs_before = set(thumb_utils.get_thumbs())

self.rb.save_thumbnail(f"{name_prefix}-{uuid4()}.png", image=content)

new_thumbs = set(thumb_utils.get_thumbs()) - thumbs_before
try:
# exactly one file must have been created (no suffixed duplicate) ...
self.assertEqual(
len(new_thumbs),
1,
msg=f"Expected a single thumbnail file, found: {sorted(new_thumbs)}",
)
# ... and it must be the one referenced by the resource
self.assertIn(os.path.basename(self.rb.thumbnail_path), new_thumbs)
finally:
thumb_utils.remove_thumbs(name_prefix)


class TestThumbnailUrl(GeoNodeBaseTestSupport):
def setUp(self):
Expand Down
Loading