مقدمه

Aspose.PDF FOSS برای Java یک کتابخانه Java با مجوز MIT است برای ایجاد و ویرایش اسناد PDF. کلاس‌های آن تحت بسته 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 می‌گیرند. سازنده نقاط چهارگانهٔ حاشیه‌نویسی را از مستطیل استخراج می‌کند، بنابراین 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() مقدار LineEnding ای مانند OpenArrow یا Diamond می‌گیرد. یک حاشیه‌نویسی جدید 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 را بازمی‌گرداند. ارسال null به یک setter آن ورودی را حذف می‌کند، و حذف آخرین محرک نیز دیکشنری /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 است، به‌جای اینکه تا خالی شدن حافظه heap رمزگشایی کند.

حد پیش‌فرض ۲۵۶ مگابایت برای هر جریان رمزگشایی‌شده است (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() به‌صورت دورانی (round-trip) پردازش می‌کنند زمانی که خروجی زیر محدودیت باقی بماند.

گزارش‌گیری تشخیصی

کتابخانه از طریق java.util.logging تحت لاگر org.aspose.pdf لاگ می‌نورد و به‌صورت پیش‌فرض ساکت است: سطح آن 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");
}

قالب‌های پشتیبانی‌شده

پشتیبانی از فرمت‌ها همان‌طور که توسط گزینه‌های بارگذاری و ذخیره‌سازی کتابخانه و دستگاه‌های رندر تأیید شده است:

قالبپسوندخواندننوشتن
PDFpdf✓✓
HTMLhtml✓✓
DOCXdocx✓✓
DOCdoc✓✓
XFDFxfdf✓✓
BMPbmp—✓
GIFgif—✓
JPEGjpeg—✓
TIFFtiff—✓
Texttxt—✓

منبع باز و مجوزدهی

Aspose.PDF FOSS برای Java تحت مجوز MIT منتشر شده است که استفاده تجاری، تغییر و توزیع مجدد را مجاز می‌داند. کد منبع و ردیاب مشکلات در github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-Java قرار دارند. این کتابخانه هدف Java نسخه 11 یا بالاتر را دارد.


شروع کار

منابع مرتبط