diff --git a/backend/apps/files/tasks.py b/backend/apps/files/tasks.py index 9050964..2b55215 100644 --- a/backend/apps/files/tasks.py +++ b/backend/apps/files/tasks.py @@ -215,7 +215,72 @@ def generate_video_thumbnail( _handle_task_error(e, file_id, "video thumbnail generation") +@shared_task(autoretry_for=(Exception,), retry_backoff=True, max_retries=5) +def generate_pdf_thumbnail( + file_id: int, page: int = 1, size: Optional[Tuple[int, int]] = None, dpi: int = 200 +) -> str: + """ + Generate PDF thumbnails using pdf2image and update the PostFileModel instance. + + Args: + file_id (int): ID of the PostFileModel instance + page (int): Page number to use for thumbnail (defaults to first page) + size (Tuple[int, int], optional): Desired thumbnail (width, height) or None to maintain original size + dpi (int): DPI for rendering the PDF (higher values result in larger images) + + Returns: + str: Success message or error message + """ + try: + from pdf2image import convert_from_path + + with transaction.atomic(): + # Retrieve the PostFileModel instance with a lock + pstfile = PostFileModel.objects.select_for_update().get(id=file_id) + + if not pstfile.file: + return "Error: PDF file not found for the given file_id." + + pdf_path = pstfile.file.path + + # Setup output path + _, thumbnail_file_path = _setup_output_path( + pstfile.hash_blake3, "pdf_thumbnail" + ) + thumbnail_filename = Path(thumbnail_file_path).name + + # Convert PDF to image using pdf2image + # first_page and last_page are 1-indexed + images = convert_from_path( + pdf_path, dpi=dpi, first_page=page, last_page=page + ) + + # Get the first page (should be the only one based on our parameters) + if not images: + raise ValueError(f"Could not extract page {page} from PDF") + + image = images[0] + + # Resize if size is specified + if size: + image = image.resize(size, PillowImage.LANCZOS) + + # Save the image + image.save(thumbnail_file_path, "PNG") + + # Update model with new thumbnail + _update_file_model(pstfile, thumbnail_file_path, thumbnail_filename) + + # Clean up temporary file os.remove(thumbnail_file_path) + return f"PDF thumbnail generated successfully for file {file_id}" + except ImportError: + error_message = ( + "pdf2image library is not installed. Install it with: pip install pdf2image" + ) + print(error_message) + raise except Exception as e: + _handle_task_error(e, file_id, "PDF thumbnail generation")