بعد أن تعرفنا على كيفية توليد ملفات pdf في الموضوع السابق توليد ملفات pdf بواسطة iText - الجزء الأول، سنرى الآن كيف نعدل ملفات موجودة مسبقا.
لهذا الغرض نستعمل الكلاس PdfContentByte التي تمثل محتوى الملف والتي تتيح لنا إضافة ما نريد لهذا المحتوى.
للحصول على كائن من هذه الكلاس، نحتاج إلى الكلاس PdfStamper التي تحتوي على الدوال getOverContent و getUnderContent. الأولى تعيد PdfContentByte يمثل مقدمة الوثيقة، أي المحتوى، getUnderContent تعيد PdfContentByte يمثل خلفية الوثيقة، والتي غالبا تكون فارغة، لكن أحيانا يمكن أن نستعملها مثلا لوضع logo الشركة على خلفية وثيقة.
سنحتاج إلى الكلاس PdfReader التي تمكننا من التعرف على خصائص الملف pdf الذي نريد تعديله، كما أن الconstructor الخاص بPdfStamper يحتاج أيضا لهذه الكلاس.
أولا ننشئ PdfReader ونممر له مسار الملف الذي نريد تعديله
PdfReader reader = new PdfReader("source.pdf");ثم ننشئ PdfStamper ونمرر له الPdfReader الذي أنشأناه، وأيضا FileOutputStream وهو يمثل الملف الذي سنكتب فيه نتيجة التعديل. أي أننا لن نعدل مباشرة في الملف الاصلي، بل سننتج ملفا جديدا يحتوي على التعديلات.
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("result.pdf"));ما سنقوم به الأن هو إضافة رقم الصفحة إلى كل صفحات الملف. لهذا الغرض نقوم بعمل loop على كل صفحات الملف، لأنه لا يوجد PdfContentByte خاص بالملف بأكمله، بل كل صفحة لها PdfContentByte خاص بها.
سنحتاج معرفة عدد صفحات الملف حتى نتمكن من عمل الloop، لذلك سنستعمل getNumberOfPages الخاصة بPdfReader
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte overContent = stamper.getOverContent(i);
//...
}بعد أن حصلنا على كائن PdfContentByte يمثل المحتوى الموجود في المقدمة، سنقوم بكتابة رقم الصفحة، لكن قبل ذلك يجب أن نحدد الخط الذي سيكتب به النص وحجمه
overContent.setFontAndSize(BaseFont.createFont(), 12);
الكلاس BaseFont هي كلاس خاصة بiText وهي تمثل خطا، الرقم 12 يمثل حجم الخط.
بعد أن حددنا الخط يجب أن نحدد المكان الذي سنكتب فيه، اي الإحداثيات x و y
overContent.setTextMatrix(reader.getPageSize(i).getWidth()/2, 20);
نريد أن نكتب في وسط الصفحة أفقيا، لذلك نسترجع عرض الصفحة الحالية ونقسمه على 2، بالنسبة للموقع العمودي فهو 20 من الاسفل!!! نعم من الاسفل، ففي iText الإحداثيات (0-0) موجودة في اسفل اليسار، وليس في أعلى اليسار كما تعودنا مع الجافا.
الآن بقي لنا أن نكتب النص الذي تريد، وهو رقم الصفحة
overContent.showText("page " + i);الشكل النهائي للloop هو كالتالي
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setFontAndSize(BaseFont.createFont(), 12);
overContent.setTextMatrix(reader.getPageSize(i).getWidth()/2, 20);
overContent.showText("page " + i);
}بعد أن أضفنا النص، سنحاول اىن إضافة صورة. كما سبق وقلت فإننا نتوفر على مكانين لإضافة محتوى ما، المقدمة، ونحصل عليها بgetOverContent والخلفية الممثلة بgetUnderContent. هاتان الصورتان توضحان الفرق,
في الحالة الأولى أضفنا الصورة للمقدمة، وفي الثانية أضفناها للخلفية.
أولا، ننشئ الصورة التي نريد إظهارها، ثم نحدد إحداثيتها، مثلا (200-200)
Image img = Image.getInstance("img.png");
img.setAbsolutePosition(200, 200);هذه الكلاس Image هي كلاس خاصة بiText ولا علاقة لها بتلك الموجودة في الحزمة java.awt.
بعد أن حصلنا على الصورة، سنعمل loop على كل صفحات الملف، كما فعلنا مع كتابة النص، لكن هنا سنستعمل getUnderContent بدل getOverContent لأننا نريد الكتابة في الخلفية
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte underContent = stamper.getUnderContent(i);
underContent.addImage(img);
}بعد أن انتهينا نقفل الPdfStamper والPdfReader
stamper.close(); reader.close();
وهذا الكود النهائي
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import java.io.FileOutputStream;
import java.io.IOException;
public class ModifyPdf {
public static void main(String[] args) {
try {
PdfReader reader = new PdfReader("source.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("result.pdf"));
//add the page number
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setFontAndSize(BaseFont.createFont(), 12);
overContent.setTextMatrix(reader.getPageSize(i).getWidth() / 2, 20);
overContent.showText("page " + i);
}
//add the image to the background
Image img = Image.getInstance("img.png");
img.setAbsolutePosition(200, 200);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte underContent = stamper.getUnderContent(i);
underContent.addImage(img);
}
stamper.close();
reader.close();
System.out.println("File modified successfully.");
} catch (DocumentException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}