import os from loguru import logger from PIL import Image from io import BytesIO from django.core.files.storage import default_storage from django import conf from django.http import HttpRequest, HttpResponse from django.contrib.auth.decorators import login_required from ..models import ImageMemo @login_required def document_thumbnail(request: HttpRequest, pk: str): """Given a document uuid, look it up, ensure that it belongs to the current user and respond with a thumbnail""" # find document with given ID (pk path param) and current user id document = ImageMemo.objects.filter(id=pk, author__id=request.user.id).first() if not document: logger.debug(f"No memo found for user={request.user.id} and memo_id={pk}") return HttpResponse(content="Document not found", status=404) # look up the file on disk # get thumb directory from django setting thumbnail_dir = getattr(conf.settings, "THUMBNAIL_DIR", "thumbnails") thumb_max_width = getattr(conf.settings, "THUMBNAIL_MAX_WIDTH", 420) thumb_path = os.path.join(thumbnail_dir, str(document.id) + ".jpg") if not default_storage.exists(thumb_path): if not default_storage.exists(document.image.name): logger.warning( f"The file associated with memo {document.id} does not exist" ) return HttpResponse(content="Document not found", status=404) # Open the image using PIL image = Image.open(default_storage.open(document.image.name)) # get the image width and height width = int(image.size[0]) height = int(image.size[1]) # find the ratio of the width to height ratio = round(width / float(height), 3) # max width of thumbnail is 240, calculate height based on ratio thumb_height = int(thumb_max_width * ratio) # Create a thumbnail image.thumbnail((thumb_max_width, thumb_height)) # Adjust size as needed # if the image format is not jpeg, convert as needed if image.format != "JPEG": image = image.convert("RGB") # Save the thumbnail to a BytesIO object thumb_io = BytesIO() image.save(thumb_io, format="JPEG") thumb_io.seek(0) default_storage.save(thumb_path, thumb_io) # Return the thumbnail as an HTTP response with open(thumb_path, "rb") as f: return HttpResponse(f.read(), content_type="image/jpeg")