Skip to content

PDFCLOUD-4775: added snippets for Annotations #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 18, 2025
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
97 changes: 97 additions & 0 deletions Uses-Cases/Annotations/annotations_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import shutil
import json
import logging
import os
from pathlib import Path
from asposepdfcloud import ApiClient, PdfApi, HighlightAnnotation, Rectangle, Color, Point, AnnotationFlags, HorizontalAlignment, VerticalAlignment, AnnotationType

# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")


class Config:
"""Configuration parameters."""
CREDENTIALS_FILE = Path(r".\credentials.json")
LOCAL_FOLDER = Path(r"C:\Samples")
REMOTE_FOLDER = "Your_Temp_Pdf_Cloud"
PDF_DOCUMENT_NAME = "sample.pdf"
LOCAL_RESULT_DOCUMENT_NAME = "output_sample.pdf"
PAGE_NUMBER = 1

ANNOTATION_ID = "GE5TAOZTHA2CYMRZGUWDIMBZFQZTEMA"

NEW_HL_ANNOTATION_TEXT = "NEW HIGHLIGHT TEXT ANNOTATION"
NEW_HL_ANNOTATION_DESCRIPTION = 'This is a sample highlight annotation'
NEW_HL_ANNOTATION_SUBJECT = "Highlight Text Box Subject"
NEW_HL_ANNOTATION_CONTENTS = "Highlight annotation sample contents"

NEW_SO_ANNOTATION_TEXT = "NEW STRIKEOUT TEXT ANNOTATION"
NEW_SO_ANNOTATION_DESCRIPTION = 'This is a sample strikeout annotation'
NEW_SO_ANNOTATION_SUBJECT = "Strikeout Text Box Subject"
NEW_SO_ANNOTATION_CONTENTS = "Strikeout annotation sample contents"

NEW_UL_ANNOTATION_TEXT = "NEW UNDERLINE TEXT ANNOTATION"
NEW_UL_ANNOTATION_DESCRIPTION = 'This is a sample underline annotation'
NEW_UL_ANNOTATION_SUBJECT = "Underline Text Box Subject"
NEW_UL_ANNOTATION_CONTENTS = "Underline annotation sample contents"

NEW_FT_ANNOTATION_TEXT = "NEW FREE TEXT ANNOTATION"
NEW_FT_ANNOTATION_DESCRIPTION = 'This is a sample annotation'
NEW_FT_ANNOTATION_SUBJECT = "Free Text Box Subject"
NEW_FT_ANNOTATION_CONTENTS = "Free Text annotation sample contents"

REPLACED_CONTENT = 'This is a replaced sample annotation'

class PdfAnnotationsHelper:
def __init__(self, credentials_file: Path):
self.pdf_api = None
self._init_api(credentials_file)

def _init_api(self, credentials_file: Path):
"""Initialize the API client."""
try:
with credentials_file.open("r", encoding="utf-8") as file:
credentials = json.load(file)
api_key, app_id = credentials.get("key"), credentials.get("id")
if not api_key or not app_id:
raise ValueError("Error: Missing API keys in the credentials file.")
self.pdf_api = PdfApi(ApiClient(api_key, app_id))
except (FileNotFoundError, json.JSONDecodeError, ValueError) as e:
logging.error(f"Failed to load credentials: {e}")

def uploadFile(self, fileName: str, localFolder: Path, remoteFolder: str):
""" Upload a local fileName to the Aspose Cloud server. """
if self.pdf_api:
file_path = localFolder / fileName
try:
self.pdf_api.upload_file(os.path.join(remoteFolder, fileName), file_path)
logging.info(f"upload_file(): File '{fileName}' uploaded successfully.")
except Exception as e:
logging.error(f"upload_document(): Failed to upload file: {e}")


def downloadFile(self, document: str, outputDocument: str, localFolder: Path, remoteFolder: Path, output_prefix: str):
"""Download the processed PDF document from the Aspose Cloud server."""
if self.pdf_api:
try:
temp_file = self.pdf_api.download_file(str(remoteFolder) + '/' + document)
local_path = localFolder / ( output_prefix + outputDocument )
shutil.move(temp_file, str(local_path))
logging.info(f"download_result(): File successfully downloaded: {local_path}")
except Exception as e:
logging.error(f"download_result(): Failed to download file: {e}")

def delete_popup_annotations(self, parent_annotation):
"""delete popup annotations for typed parent annotation in the page in the PDF document."""
if self.pdf_api:
args = {
"folder": Config.REMOTE_FOLDER
}
response = self.pdf_api.get_document_popup_annotations(Config.PDF_DOCUMENT_NAME, **args)
if response.code == 200:
for annotation in response.annotations.list:
if annotation.parent.id == parent_annotation:
self.pdf_api.delete_annotation(Config.PDF_DOCUMENT_NAME, annotation.id, **args)
logging.info(f"delete_popup_annotations(): popup annotation id = '{annotation.id}' for '{annotation.contents}' deleted in the document '{Config.PDF_DOCUMENT_NAME}'.")
else:
logging.error(f"delete_popup_annotations(): Failed to delete popup annotation in the document. Response code: {response.code}")
40 changes: 40 additions & 0 deletions Uses-Cases/Annotations/annotations_launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from annotations_helper import PdfAnnotationsHelper, Config
from get_annotations import PdfGetAnnotations
from get_annotation_by_id import PdfGetAnnotationById
from new_highlight_annotation import PdfAddHighlightAnnotations
from new_strikeout_annotation import PdfAddStrikeoutAnnotations
from new_text_annotation import PdfAddFreeTextAnnotations
from new_underline_annotation import PdfAddUnderlineAnnotations
from delete_page_annotations import PdfDelPageAnnotations
from delete_text_annotation import PdfDalTextAnnotations
from replace_annotation import PdfReplaceAnnotations

if __name__ == "__main__":
helper = PdfAnnotationsHelper(Config.CREDENTIALS_FILE)

modify_ant = PdfReplaceAnnotations(helper.pdf_api, helper)
modify_ant.modify_annotation()

get_ant = PdfGetAnnotations(helper.pdf_api, helper)
annotation_id =get_ant.request_annotations()

rq_ant = PdfGetAnnotationById(helper.pdf_api, helper)
rq_ant.request_annotation(annotation_id)

del_ant = PdfDalTextAnnotations(helper.pdf_api, helper)
del_ant.delete_annotation()

del_page_ant = PdfDelPageAnnotations(helper.pdf_api, helper)
del_page_ant.delete_page_annotations()

add_hl = PdfAddHighlightAnnotations(helper.pdf_api, helper)
add_hl.append_highlight_annotation()

add_so = PdfAddStrikeoutAnnotations(helper.pdf_api, helper)
add_so.append_strikeout_annotation()

add_ft = PdfAddFreeTextAnnotations(helper.pdf_api, helper)
add_ft.append_text_annotation()

add_ul = PdfAddUnderlineAnnotations(helper.pdf_api, helper)
add_ul.append_underline_annotation()
25 changes: 25 additions & 0 deletions Uses-Cases/Annotations/delete_page_annotations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

from annotations_helper import Config, PdfAnnotationsHelper, logging
from asposepdfcloud import PdfApi

class PdfDelPageAnnotations:
"""Class for managing PDF annotations using Aspose PDF Cloud API."""
def __init__(self, pdf_api: PdfApi, helper: PdfAnnotationsHelper):
self.pdfApi = pdf_api
self.helper = helper

def delete_page_annotations(self):
"""Delete annotation from the PDF document."""
if self.pdfApi:
self.helper.uploadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)

args = {
"folder": Config.REMOTE_FOLDER
}

response = self.pdfApi.delete_page_annotations(Config.PDF_DOCUMENT_NAME, Config.PAGE_NUMBER, **args)
if response.code == 200:
logging.info(f"delete_annotation(): annotations on page '{Config.PAGE_NUMBER}' deleted from the document '{Config.PDF_DOCUMENT_NAME}'.")
self.helper.downloadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_RESULT_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER, "del_page_annotations_")
else:
logging.error(f"delete_annotation(): Failed to delete annotation from the document. Response code: {response.code}")
28 changes: 28 additions & 0 deletions Uses-Cases/Annotations/delete_text_annotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

from annotations_helper import Config, PdfAnnotationsHelper, logging
from asposepdfcloud import PdfApi

class PdfDalTextAnnotations:
"""Class for managing PDF annotations using Aspose PDF Cloud API."""
def __init__(self, pdf_api: PdfApi, helper: PdfAnnotationsHelper):
self.pdfApi = pdf_api
self.helper = helper

def delete_annotation(self):
"""Delete annotation from the PDF document."""
if self.pdfApi:
if Config.ANNOTATION_ID is None:
logging.info(f"delete_annotation(): annotation id not defined!")
return
self.helper.uploadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)

args = {
"folder": Config.REMOTE_FOLDER
}
response = self.pdfApi.delete_annotation(Config.PDF_DOCUMENT_NAME, Config.ANNOTATION_ID, **args)
self.helper.delete_popup_annotations(Config.ANNOTATION_ID)
if response.code == 200:
logging.info(f"delete_annotation(): annotation '{Config.ANNOTATION_ID}' deleted from the document '{Config.PDF_DOCUMENT_NAME}'.")
self.helper.downloadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_RESULT_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER, "del_annotation_")
else:
logging.error(f"delete_annotation(): Failed to delete annotation from the document. Response code: {response.code}")
22 changes: 22 additions & 0 deletions Uses-Cases/Annotations/get_annotation_by_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from annotations_helper import Config, PdfAnnotationsHelper, logging
from asposepdfcloud import PdfApi, AnnotationsInfoResponse

class PdfGetAnnotationById:
"""Class for managing PDF annotations using Aspose PDF Cloud API."""
def __init__(self, pdf_api: PdfApi, helper: PdfAnnotationsHelper):
self.pdfApi = pdf_api
self.helper = helper

def request_annotation(self, annotation_id):
"""Get annotation from the page in the PDF document."""
if self.pdfApi:
self.helper.uploadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)

args = {
"folder": Config.REMOTE_FOLDER
}
response = self.pdfApi.get_text_annotation(Config.PDF_DOCUMENT_NAME, annotation_id, **args)
if response.code == 200:
logging.info(f"get_annotationn(): annotation '{annotation_id}' successfully found '{response.annotation.contents}' in the document '{Config.PDF_DOCUMENT_NAME}'.")
else:
logging.error(f"get_annotation(): Failed to get annotation in the document. Response code: {response.code}")
28 changes: 28 additions & 0 deletions Uses-Cases/Annotations/get_annotations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from annotations_helper import Config, PdfAnnotationsHelper, logging
from asposepdfcloud import PdfApi, AnnotationsInfoResponse

class PdfGetAnnotations:
"""Class for managing PDF annotations using Aspose PDF Cloud API."""
def __init__(self, pdf_api: PdfApi, helper: PdfAnnotationsHelper):
self.pdfApi = pdf_api
self.helper = helper

def request_annotations(self):
"""Get annotations from the page in the PDF document."""
if self.pdfApi:
self.helper.uploadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)

args = {
"folder": Config.REMOTE_FOLDER
}
annotation_result = ''
response: AnnotationsInfoResponse = self.pdfApi.get_page_annotations(Config.PDF_DOCUMENT_NAME, Config.PAGE_NUMBER, **args)
if response.code == 200:
for annotation in response.annotations.list:
if annotation.annotation_type == "Text":
logging.info(f"get_annotations(): annotation id={annotation.id} with '{annotation.contents}' content get from the document '{Config.PDF_DOCUMENT_NAME}' on {annotation.page_index} page.")
annotation_result = annotation.id
return annotation_result
else:
logging.error(f"get_annotations(): Failed to get annotation in the document. Response code: {response.code}")
return annotation_result
47 changes: 47 additions & 0 deletions Uses-Cases/Annotations/new_highlight_annotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from annotations_helper import Config, PdfAnnotationsHelper, logging
from asposepdfcloud import PdfApi, HighlightAnnotation, Rectangle, Color, Point, AnnotationFlags, HorizontalAlignment, VerticalAlignment

class PdfAddHighlightAnnotations:
"""Class for managing PDF annotations using Aspose PDF Cloud API."""
def __init__(self, pdf_api: PdfApi, helper: PdfAnnotationsHelper):
self.pdfApi = pdf_api
self.helper = helper

def append_highlight_annotation(self):
"""Append a new highlight text annotation to the PDF document."""
if self.pdfApi:
self.helper.uploadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)

args = {
"folder": Config.REMOTE_FOLDER
}

new_annotation = HighlightAnnotation(
rect = Rectangle(llx=100, lly=350, urx=450, ury=400),
name = 'Highlight_Text_Annotation',
flags = [AnnotationFlags.DEFAULT],
horizontal_alignment = HorizontalAlignment.LEFT,
vertical_alignment = VerticalAlignment.TOP,
rich_text = Config.NEW_HL_ANNOTATION_TEXT,
subject = Config.NEW_HL_ANNOTATION_SUBJECT,
contents= Config.NEW_HL_ANNOTATION_CONTENTS,
title = Config.NEW_HL_ANNOTATION_DESCRIPTION,
z_index = 1,
color=Color(a=0xFF, r=0, g=0xFF, b=0),
quad_points = [
Point(10, 10),
Point(20, 10),
Point(10, 20),
Point(10, 10)
],
modified = '03/27/2025 00:00:00.000 AM',
)
try:
response = self.pdfApi.post_page_highlight_annotations(Config.PDF_DOCUMENT_NAME, Config.PAGE_NUMBER, [new_annotation], **args)
if response.code == 200:
logging.info(f"append_highlight_annotation(): annotation '{Config.NEW_HL_ANNOTATION_TEXT}' added to the document '{Config.PDF_DOCUMENT_NAME}'.")
self.helper.downloadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_RESULT_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER, "add_highlight_")
else:
logging.error(f"append_highlight_annotation(): Failed to add annotation to the document. Response code: {response.code}")
except Exception as e:
logging.error(f"append_highlight_annotation(): Error while adding annotation: {e}")
47 changes: 47 additions & 0 deletions Uses-Cases/Annotations/new_strikeout_annotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from annotations_helper import Config, PdfAnnotationsHelper, logging
from asposepdfcloud import PdfApi, StrikeOutAnnotation, Rectangle, Color, Point, AnnotationFlags, HorizontalAlignment, VerticalAlignment

class PdfAddStrikeoutAnnotations:
"""Class for managing PDF annotations using Aspose PDF Cloud API."""
def __init__(self, pdf_api: PdfApi, helper: PdfAnnotationsHelper):
self.pdfApi = pdf_api
self.helper = helper

def append_strikeout_annotation(self):
"""Append a new strikeout text annotation to the PDF document."""
if self.pdfApi:
self.helper.uploadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)

args = {
"folder": Config.REMOTE_FOLDER
}

new_annotation = StrikeOutAnnotation(
rect = Rectangle(llx=100, lly=100, urx=200, ury=200),
name = 'Strikeout_Text_Annotation',
flags = [AnnotationFlags.DEFAULT],
horizontal_alignment = HorizontalAlignment.LEFT,
vertical_alignment = VerticalAlignment.TOP,
rich_text = Config.NEW_SO_ANNOTATION_TEXT,
subject = Config.NEW_SO_ANNOTATION_SUBJECT,
title = Config.NEW_SO_ANNOTATION_DESCRIPTION,
contents= Config.NEW_SO_ANNOTATION_CONTENTS,
z_index = 1,
color= Color(a=0xFF, r=0, g=0xFF, b=0),
quad_points = [
Point(10, 10),
Point(20, 10),
Point(10, 20),
Point(10, 10)
],
modified = '03/27/2025 00:00:00.000 AM',
)
try:
response = self.pdfApi.post_page_strike_out_annotations(Config.PDF_DOCUMENT_NAME, Config.PAGE_NUMBER, [new_annotation], **args)
if response.code == 200:
logging.info(f"append_strikeout_annotation(): annotation '{Config.NEW_SO_ANNOTATION_TEXT}' added to the document '{Config.PDF_DOCUMENT_NAME}'.")
self.helper.downloadFile(Config.PDF_DOCUMENT_NAME, Config.LOCAL_RESULT_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER, "add_strikeout_")
else:
logging.error(f"append_strikeout_annotation(): Failed to add annotation to the document. Response code: {response.code}")
except Exception as e:
logging.error(f"append_strikeout_annotation(): Error while adding annotation: {e}")
Loading