소개
Aspose.PDF FOSS for Java은 PDF 문서를 생성하고 편집하기 위한 MIT 라이선스 Java 라이브러리입니다. 클래스는 org.aspose.pdf 패키지와 그 하위 패키지(org.aspose.pdf.annotations, org.aspose.pdf.forms, org.aspose.pdf.facades 등) 아래에 정리되어 있으며, Document가 대부분의 워크플로우에 대한 진입점입니다. 이 라이브러리는 타사 런타임 종속성이 없으며, Maven 빌드에서 유일한 종속성은 테스트 범위의 JUnit입니다.
library announcement, facades post, page-editing post은 이미 문서 생성, 폼 필드, 추출·암호화·스탬핑을 위한 파사드 클래스, 그리고 PdfFileEditor를 사용한 페이지 작업을 다루고 있습니다. 이 게시물은 해당 게시물들이 다루지 않은 동일한 API의 다섯 가지 다른 영역을 설명합니다: 텍스트 마크업 주석, 자유 텍스트 콜아웃, 문서 수준 액션, 스트림 디코딩 시 크기 보호, 진단 로깅.
각 영역은 작고 독립적인 API입니다. 아래 섹션에서는 호출 방법, 기본값, 그리고 라이브러리 자체 테스트가 확인한 엣지 케이스를 보여줍니다.
핵심 기능
텍스트 마크업 주석
HighlightAnnotation, UnderlineAnnotation, StrikeOutAnnotation, SquigglyAnnotation은 각각 Page와 Rectangle를 받습니다. 생성자는 사각형에서 주석의 사변점(quad points)을 유도하므로 getQuadPoints()은 수동 계산 없이 여덟 개의 값을 반환합니다. 사각형 (100, 200, 300, 250)에 대해 결과는 [100, 250, 300, 250, 100, 200, 300, 200]이며, 순서는 왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래입니다. setQuadPoints()은 유도된 값을 사용자가 제공한 여덟 값 배열로 교체하고, 기존 사전에서 재구성된 주석은 이미 저장된 사변점을 유지합니다. getSubtype()은 PDF 서브타입 이름을 반환합니다: Highlight, Underline, StrikeOut, 또는 Squiggly.
주석을 생성해도 페이지에 부착되지 않습니다. page.getAnnotations().add(...)으로 추가하세요.
try (Document doc = new Document()) {
Page page = doc.getPages().add();
HighlightAnnotation highlight = new HighlightAnnotation(page, new Rectangle(100, 200, 300, 250));
double[] quadPoints = highlight.getQuadPoints();
UnderlineAnnotation underline = new UnderlineAnnotation(page, new Rectangle(50, 100, 200, 120));
StrikeOutAnnotation strikeOut = new StrikeOutAnnotation(page, new Rectangle(50, 140, 200, 160));
SquigglyAnnotation squiggly = new SquigglyAnnotation(page, new Rectangle(50, 180, 200, 200));
page.getAnnotations().add(highlight);
page.getAnnotations().add(underline);
page.getAnnotations().add(strikeOut);
page.getAnnotations().add(squiggly);
doc.save("markup.pdf");
}
자유 텍스트 콜아웃
FreeTextAnnotation은(는) 텍스트를 페이지에 직접 배치합니다. 세 인자 생성자는 DefaultAppearance을(를) 받아서 글꼴 이름, 글꼴 크기 및 텍스트 색상을 포함합니다. 세 가지 속성이 콜아웃을 형성합니다:
setIntent()은(는)FreeTextIntent을(를) 받습니다:FreeText,FreeTextCallout또는FreeTextTypeWriter. 새로운 주석은Undefined을(를) 보고하고,null을(를) 전달하면 해당 상태로 돌아갑니다.setCallout()은(는) 콜아웃 라인을 두 개 또는 세 개의{x, y}점 배열로 받습니다. 다른 길이의 배열은 무시되고 기존 콜아웃은 그대로 유지됩니다;null은(는) 콜아웃을 제거합니다.setEndingStyle()은(는)OpenArrow또는Diamond와 같은LineEnding값을 받습니다. 새로운 주석은LineEnding.None을(를) 보고합니다.
try (Document doc = new Document()) {
Page page = doc.getPages().add();
DefaultAppearance da = new DefaultAppearance("Helv", 10, Color.BLACK);
FreeTextAnnotation note = new FreeTextAnnotation(page, new Rectangle(50, 50, 200, 100), da);
note.setContents("Check this value");
note.setIntent(FreeTextIntent.FreeTextCallout);
note.setCallout(new double[][] {{10, 10}, {50, 50}, {100, 100}});
note.setEndingStyle(LineEnding.OpenArrow);
page.getAnnotations().add(note);
doc.save("callout.pdf");
}
저장된 주석 딕셔너리는 이러한 값을 /IT, /CL, 및 /LE로 저장합니다.
문서 수준 작업
Document.getActions()은 DocumentActions 보기를 반환합니다. setOpenAction()은 카탈로그의 /OpenAction 항목에 동작을 저장합니다. 추가 트리거 다섯 개, setBeforeClosing(), setBeforeSaving(), setAfterSaving(), setBeforePrinting(), setAfterPrinting()는 카탈로그의 /AA 추가-동작 사전에 독립적으로 저장됩니다.
각 getter는 트리거가 설정될 때까지 null을 반환합니다. setter에 null을 전달하면 해당 항목이 제거되고, 마지막 트리거를 제거하면 /AA 사전도 제거됩니다. 동작은 PdfAction 인스턴스이며, GoToURIAction는 UriAction의 별칭이고, 그 getType()은 URI을 반환합니다. DocumentActions 객체는 실시간 뷰이므로, 이후에 getActions()를 호출하면 이전 호출을 통해 이루어진 변경을 확인할 수 있으며, 저장된 파일을 다시 열 때 트리거가 다시 읽힙니다.
try (Document doc = new Document()) {
doc.getPages().add();
DocumentActions actions = doc.getActions();
actions.setOpenAction(new GoToURIAction("https://example.com"));
actions.setBeforeSaving(new GoToURIAction("https://example.com/saving"));
PdfAction open = doc.getActions().getOpenAction();
if (open instanceof UriAction) {
System.out.println(((UriAction) open).getUri());
}
actions.setBeforeSaving(null); // removes /WS; /AA is removed once it is empty
doc.save("actions.pdf");
}
스트림 필터에 대한 디코드 제한
PDF 스트림은 인코딩된 형태로 저장되며, 손상되었거나 악의적인 스트림은 저장된 크기보다 훨씬 크게 확장될 수 있습니다. DecodeLimits은 FlateDecode, LZWDecode 및 RunLengthDecode 필터가 공유하는 보호 장치입니다. 스트림의 디코드된 출력이 상한을 초과하면, 필터는 힙이 고갈될 때까지 디코딩하는 대신 DecodeSizeLimitException을 발생시키며, 이는 IOException의 서브클래스입니다.
기본 상한은 디코드된 스트림당 256MB(DecodeLimits.DEFAULT_MAX_DECODED_BYTES)입니다. 이를 변경하려면 DecodeLimits.PROPERTY이라는 시스템 속성을 aspose.pdf.maxDecodedStreamBytes으로 설정하고 바이트 단위 크기로 지정하십시오; 0 이하의 값은 보호 장치를 비활성화합니다. 이 속성은 각 디코드 시마다 읽히므로 런타임에 변경할 수 있습니다.
static byte[] decodeFlate(byte[] encoded) {
// Lower the cap to 16 MB (16777216 bytes) for this process
System.setProperty(DecodeLimits.PROPERTY, "16777216");
try {
return new FlateFilter().decode(encoded, null);
} catch (IOException e) {
// "FlateDecode: decoded output exceeds 16777216 bytes - likely a corrupt stream
// or decompression bomb (override with -Daspose.pdf.maxDecodedStreamBytes)"
return null;
}
}
상한 이하의 스트림은 일반적으로 디코드됩니다. FlateFilter과 RunLengthFilter은 출력이 제한 이하일 때 encode()와 decode()을 통해 데이터를 라운드트립합니다.
진단 로깅
이 라이브러리는 org.aspose.pdf 로거 아래에서 java.util.logging을 통해 로그를 기록하며 기본적으로는 무음 상태입니다: 로그 레벨은 OFF입니다. AsposePdfLogging은 로그를 활성화합니다.
setLevel(Level)은(는) 코드에서 레벨을 설정합니다;null은(는) 라이브러리를OFF로 반환합니다.getLevel()은(는) 이를 다시 읽어옵니다.aspose.pdf.log시스템 속성(또는AsposePdfLogging.LOG_PROPERTY으로도 사용 가능)은 명령줄에서 이를 설정합니다.configureFromSystemProperty()는 해당 속성을 적용하고 클래스가 로드될 때도 실행됩니다. 값on과warning는WARNING를 선택하고,verbose는FINE을 선택하며,debug는ALL를 선택합니다.java.util.logging.Level이름(예:SEVERE)은 모두 허용되고, 인식되지 않은 값은OFF로 대체됩니다.
WARNING은 엔진의 경고를 통과시킵니다; FINE, 즉 verbose 설정도 파서의 복구 상세 정보를 통과시킵니다. AsposePdfLogging은 org.aspose.pdf 로거 서브트리만 변경합니다. 이는 루트 로거의 레벨을 변경하지 않으며, 라이브러리 로거는 기록을 루트 로거의 핸들러로 전달하지 않습니다. 로깅이 활성화되고 라이브러리 로거에 핸들러가 연결되지 않은 경우, 콘솔 핸들러가 설치됩니다.
// Equivalent to starting the JVM with -Daspose.pdf.log=warning
AsposePdfLogging.setLevel(Level.WARNING);
System.setProperty(AsposePdfLogging.LOG_PROPERTY, "verbose");
AsposePdfLogging.configureFromSystemProperty();
System.out.println(AsposePdfLogging.getLevel()); // FINE
빠른 시작
빌드에 종속성을 추가하세요:
<dependency>
<groupId>org.aspose</groupId>
<artifactId>aspose-pdf-foss</artifactId>
<version>26.8.0</version>
</dependency>다음 예제는 페이지를 생성하고, 하이라이트와 자유 텍스트 호출을 추가한 후 문서를 저장합니다:
import org.aspose.pdf.*;
import org.aspose.pdf.annotations.*;
try (Document doc = new Document()) {
Page page = doc.getPages().add();
page.getAnnotations().add(new HighlightAnnotation(page, new Rectangle(100, 200, 300, 250)));
FreeTextAnnotation note = new FreeTextAnnotation(page, new Rectangle(50, 50, 200, 100),
new DefaultAppearance("Helv", 10, Color.BLACK));
note.setContents("Check this value");
note.setIntent(FreeTextIntent.FreeTextCallout);
note.setCallout(new double[][] {{10, 10}, {50, 50}, {100, 100}});
page.getAnnotations().add(note);
doc.save("core-features.pdf");
}
지원 포맷
라이브러리의 로드 및 저장 옵션과 렌더링 장치에 의해 확인된 형식 지원:
| 포맷 | 확장자 | 읽기 | 쓰기 |
|---|---|---|---|
| ✓ | ✓ | ||
| HTML | html | ✓ | ✓ |
| DOCX | docx | ✓ | ✓ |
| DOC | doc | ✓ | ✓ |
| XFDF | xfdf | ✓ | ✓ |
| BMP | bmp | — | ✓ |
| GIF | gif | — | ✓ |
| JPEG | jpeg | — | ✓ |
| TIFF | tiff | — | ✓ |
| Text | txt | — | ✓ |
오픈 소스 & 라이선스
Aspose.PDF FOSS for Java은 MIT 라이선스로 출시되었으며, 상업적 사용, 수정 및 재배포를 허용합니다. 소스 코드와 이슈 트래커는 github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-Java에 있습니다. 이 라이브러리는 Java 11 이상을 대상으로 합니다.