Как я могу добавить исходный контент PDF в целевой PDF, используя IText7, не теряя верхний и нижний колонтитулы? - PullRequest
1 голос
/ 10 июня 2019

Я использую Itext 7. У меня есть два PDF.Исходный PDF имеет некоторое содержание.Целевой PDF имеет верхний и нижний колонтитулы.У меня есть требование добавить содержимое из исходного PDF в целевой PDF в середине страницы без наложения верхнего и нижнего колонтитула целевого PDF.Может ли кто-нибудь помочь мне с кодом?

Ниже мой код и прикрепленный документ - скриншот исходного PDF, который необходимо встроить в final.pdf

enter image description here

import java.io.File;
import java.io.FileOutputStream;
import java.net.MalformedURLException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;

public class TestPdf {

    public static void main(String[] args) {

        String uuid = UUID.randomUUID().toString();
          try{                           
              @SuppressWarnings("resource")
              PdfWriter writer = new PdfWriter(new FileOutputStream(new File(Paths.get("Output").toAbsolutePath()+"/final.pdf"))).setSmartMode(true);
              PdfDocument pdfDoc = new PdfDocument(writer);    
              pdfDoc.setDefaultPageSize(PageSize.A4.rotate());                                                              
              String fonts[] = {Paths.get("fonts").toAbsolutePath() + "/TREBUC.TTF", Paths.get("fonts").toAbsolutePath() + "/TREBUCBD.TTF", Paths.get("fonts").toAbsolutePath() + "/TREBUCBI.TTF",Paths.get("fonts").toAbsolutePath() + "/TREBUCIT.TTF"};
              FontProvider fontProvider = new FontProvider();
               Map<String, PdfFont> pdfFontMap = new HashMap();
              for (String font : fonts) {
                 FontProgram fontProgram = FontProgramFactory.createFont(font);
                 if(font.endsWith("TREBUC.TTF")) {
                     pdfFontMap.put("NORMAL", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 } else if(font.endsWith("TREBUCBD.TTF")) {
                     pdfFontMap.put("BOLD", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 } else if(font.endsWith("TREBUCBI.TTF")) {
                     pdfFontMap.put("BOLD_ITALIC", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 } else if(font.endsWith("TREBUCIT.TTF")) {
                     pdfFontMap.put("ITALIC", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 }

                 fontProvider.addFont(fontProgram);
              }
             TestPdf testPdf = new TestPdf();
              NormalPageHeader headerHandler = testPdf.new NormalPageHeader(Paths.get("images").toAbsolutePath() + "\\logo.png", pdfFontMap);
              pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
              PageEndEvent pageEndEvent = testPdf.new PageEndEvent(Paths.get("images").toAbsolutePath() + "\\FooterLineExternal.png" ,pdfFontMap);
              pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, pageEndEvent);
              Document doc = new Document(pdfDoc);

               doc.getPageEffectiveArea(PageSize.A4.rotate());
               Table imageTable = new Table(1);
               imageTable.setBorder(Border.NO_BORDER);
               imageTable.setWidth(UnitValue.createPercentValue(100));
               Cell cell = new Cell();
               Paragraph paragraph = new Paragraph("Title");
               paragraph.setVerticalAlignment(VerticalAlignment.TOP);
               cell.add(paragraph);            
               cell.setBorder(Border.NO_BORDER);
               cell.setPaddingTop(50);
               imageTable.addCell(cell);
               doc.add(imageTable);
               doc.close();
               System.out.println("Converted to PDF Succesfully >>> convertedSvg_"+uuid+".pdf");
           }catch(Exception e){
               e.printStackTrace();
               System.out.println("Error Occured while converting to PDF = " + e.getMessage());
           }
        }   


    class NormalPageHeader implements IEventHandler {

         String header;
         Map<String, PdfFont> font;
         public NormalPageHeader(String header, Map<String, PdfFont> font) {
             this.header = header;
             this.font = font;
         }

         @Override
         public void handleEvent(Event event) {
             //Retrieve document and
                PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
                PdfDocument pdf = docEvent.getDocument();
                PdfPage page = docEvent.getPage();         
                Rectangle pageSize = page.getPageSize();
                PdfCanvas pdfCanvas = new PdfCanvas(
                page.getLastContentStream(), page.getResources(), pdf);
                Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
                  canvas.setFontSize(10f);
                  Table table = new Table(3);
                  table.setBorder(Border.NO_BORDER);
                  table.setWidth(UnitValue.createPercentValue(100));
                  Cell leftCell = new Cell();
                  leftCell.setFont(font.get("NORMAL"));
                  leftCell.setPaddingTop(15);
                  leftCell.setPaddingLeft(20);
                  leftCell.setBorder(Border.NO_BORDER);
                  leftCell.setBorderBottom(new SolidBorder(0.5f));
                  leftCell.setWidth(UnitValue.createPercentValue(33.3f));
                  Text userLabel = new Text("Username: ");
                  userLabel.setBold();
                  Paragraph paragraph = new Paragraph(userLabel);
                  Cell middleCell = new Cell();
                  middleCell.setFont(font.get("NORMAL"));
                  middleCell.setPaddingTop(15);
                  middleCell.setBorder(Border.NO_BORDER);
                  middleCell.setBorderBottom(new SolidBorder(0.5f));
                  middleCell.setWidth(UnitValue.createPercentValue(33.3f));
                  paragraph = new Paragraph("Main Header");
                  paragraph.setTextAlignment(TextAlignment.CENTER);
                  paragraph.setBold();
                  paragraph.setFontSize(12);
                  middleCell.add(paragraph);
                  String programString = "Sample header";                 
                  paragraph = new Paragraph(programString);
                  paragraph.setTextAlignment(TextAlignment.CENTER);
                  paragraph.setBold();
                  paragraph.setFontSize(10);
                  middleCell.add(paragraph);

                  table.addCell(middleCell);
                  Cell rightCell = new Cell();
                  rightCell.setFont(font.get("NORMAL"));
                  rightCell.setPaddingTop(20);
                  rightCell.setWidth(UnitValue.createPercentValue(33.3f));
                  rightCell.setHorizontalAlignment(HorizontalAlignment.RIGHT);
                  rightCell.setBorder(Border.NO_BORDER);
                  rightCell.setBorderBottom(new SolidBorder(0.5f));
                  rightCell.setPaddingRight(20);
                  //Write text at position
                  Image img;
                try {
                    img = new Image(ImageDataFactory.create(header));
                    img.setHorizontalAlignment(HorizontalAlignment.RIGHT);
                    Style style = new Style();
                    style.setWidth(91);
                    style.setHeight(25);

                     img.addStyle(style);
                     rightCell.add(img);
                     table.addCell(rightCell);
                     table.setMarginLeft(15);
                     table.setMarginRight(15);
                     canvas.add(table);
                } catch (MalformedURLException e) {

                    e.printStackTrace();
                }
         }

     }

    class PageEndEvent implements IEventHandler {

         protected PdfFormXObject placeholder;
         protected float side = 20;
         protected float x = 300;
         protected float y = 10;
         protected float space = 4.5f;
         private String bar;
         protected float descent = 3;
         Map<String, PdfFont> font;
         public PageEndEvent(String bar, Map<String, PdfFont> font) {            
             this.bar = bar;
             this.font = font;
             placeholder =new PdfFormXObject(new Rectangle(0, 0, side, side));
         }

         @Override
         public void handleEvent(Event event) {
             Table table = new Table(3);
             table.setBorder(Border.NO_BORDER);
             table.setWidth(UnitValue.createPercentValue(100));
             Cell confCell = new Cell();
             confCell.setFont(font.get("NORMAL"));
             confCell.setPaddingTop(15);
             confCell.setPaddingLeft(20);
             confCell.setBorder(Border.NO_BORDER);
             confCell.setBorderBottom(new SolidBorder(0.5f));
             confCell.setWidth(UnitValue.createPercentValue(100));
             PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
             PdfDocument pdf = docEvent.getDocument();
             PdfPage page = docEvent.getPage();
             Rectangle pageSize = page.getPageSize();
             PdfCanvas pdfCanvas = new PdfCanvas(
             page.getLastContentStream(), page.getResources(), pdf);
             Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
             Image img;
            try {
                 img = new Image(ImageDataFactory.create(bar));
                 img.setHorizontalAlignment(HorizontalAlignment.LEFT);
                 Style style = new Style();
                 style.setWidth(UnitValue.createPercentValue(100));
                 style.setHeight(50);
                 img.addStyle(style);
                 Paragraph p = new Paragraph().add("Test: Confidential");
                 p.setFont(font.get("NORMAL"));
                 p.setFontSize(8);
                 p.setFontColor(com.itextpdf.kernel.colors.ColorConstants.GRAY);
                 canvas.showTextAligned(p, x, y, TextAlignment.CENTER);
                 pdfCanvas.addXObject(placeholder, x + space, y - descent);
                 pdfCanvas.release();
            } catch (MalformedURLException e) {

                e.printStackTrace();
            }

         }

         public void writeTotal(PdfDocument pdf) {

             Canvas canvas = new Canvas(placeholder, pdf);

             canvas.showTextAligned(String.valueOf(pdf.getNumberOfPages()),

                     0, descent, TextAlignment.LEFT);

         }

     }

}

1 Ответ

1 голос
/ 12 июня 2019

Прежде всего, несколько слов об архитектуре iText, стоящих за некоторыми используемыми вами конструкциями:

Когда вы используете экземпляр Document для добавления контента в документ, который iText должен автоматически разметить, предполагается, что областьгде iText может макетировать всю страницу за вычетом полей страницы.

Таким образом, если вы добавляете дополнительный материал страницы через другие каналы, кроме Document, например, как вы делаете в своих NormalPageHeader headerHandler и PageEndEvent pageEndEvent это ваша ответственность сделать это за пределами области макета , описанной выше, то есть в областях полей.(Если этот дополнительный материал не является фоновым материалом, например, водяным знаком ...)

Для этого вы должны установить поля достаточно большими, чтобы гарантировать, что ваш дополнительный материал находится на полях.По умолчанию поля страницы установлены на 36pt на каждой стороне страницы, что обычно достаточно для однострочного или нижнего колонтитула, но не совсем для многострочных.

В вашем коде вы создаете заголовок, который требуетпо крайней мере, около 52pt плюс бит, чтобы содержимое iText не коснулось строки заголовка.

Учитывая это, довольно просто вставить данный PdfPage sourcePage в вашу страницу:

...
NormalPageHeader headerHandler = testPdf.new NormalPageHeader(Paths.get("images").toAbsolutePath() + "\\logo.png", pdfFontMap);
pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
PageEndEvent pageEndEvent = testPdf.new PageEndEvent(Paths.get("images").toAbsolutePath() + "\\FooterLineExternal.png" ,pdfFontMap);
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, pageEndEvent);

Document doc = new Document(pdfDoc);
doc.setTopMargin(55);
PdfFormXObject xobject = sourcePage.copyAsFormXObject(pdfDoc);
Rectangle xobjectBoundaryBox = xobject.getBBox().toRectangle();
xobject.getPdfObject().put(PdfName.Matrix, new PdfArray(new float[] {1, 0, 0, 1, -xobjectBoundaryBox.getLeft(), -xobjectBoundaryBox.getBottom()}));
Image image = new Image(xobject);
image.setAutoScale(true);
doc.add(image);

doc.close();
...

(выдержка из InsertInSpace helper insertIntoNithinTestFile)


Если вы используете исходную исходную страницу как есть, приведенный выше код будет вставленэто в том числе все пространство на полях.Если вы не хотите этого, а вместо этого урезаете это пространство, вы можете выполнить следующие действия, чтобы определить фактическую ограничивающую рамку содержимого страницы, уменьшить страницу до этой рамки и перенаправить ее к методу insertIntoNithinTestFile выше, предполагая, что страницаОбрабатывается 1 из PdfDocument pdfDocument:

PdfDocumentContentParser contentParser = new PdfDocumentContentParser(pdfDocument);
MarginFinder strategy = contentParser.processContent(1, new MarginFinder());

PdfPage page = pdfDocument.getPage(1);
page.setCropBox(strategy.getBoundingBox());
page.setMediaBox(strategy.getBoundingBox());
insertIntoNithinTestFile(page, "test-InsertIntoNithinTestFile.pdf");

( InsertInSpace test testInsertSimpleTestPdf)

MarginFinder - это портiText5 MarginFinder до iText 7:

public class MarginFinder implements IEventListener {
    public Rectangle getBoundingBox() {
        return boundingBox != null ? boundingBox.clone() : null;
    }

    @Override
    public void eventOccurred(IEventData data, EventType type) {
        if (data instanceof ImageRenderInfo) {
            ImageRenderInfo imageData = (ImageRenderInfo) data;
            Matrix ctm = imageData.getImageCtm();
            for (Vector unitCorner : UNIT_SQUARE_CORNERS) {
                Vector corner = unitCorner.cross(ctm);
                addToBoundingBox(new Rectangle(corner.get(Vector.I1), corner.get(Vector.I2), 0, 0));
            }
        } else if (data instanceof TextRenderInfo) {
            TextRenderInfo textRenderInfo = (TextRenderInfo) data;
            addToBoundingBox(textRenderInfo.getAscentLine().getBoundingRectangle());
            addToBoundingBox(textRenderInfo.getDescentLine().getBoundingRectangle());
        } else if (data instanceof PathRenderInfo) {
            PathRenderInfo renderInfo = (PathRenderInfo) data;
            if (renderInfo.getOperation() != PathRenderInfo.NO_OP)
            {
                Matrix ctm = renderInfo.getCtm();
                Path path = renderInfo.getPath();
                for (Subpath subpath : path.getSubpaths())
                {
                    for (Point point2d : subpath.getPiecewiseLinearApproximation())
                    {
                        Vector vector = new Vector((float)point2d.getX(), (float)point2d.getY(), 1);
                        vector = vector.cross(ctm);
                        addToBoundingBox(new Rectangle(vector.get(Vector.I1), vector.get(Vector.I2), 0, 0));
                    }
                }
            }
        } else if (data != null) {
            logger.fine(String.format("Ignored %s event, class %s.", type, data.getClass().getSimpleName()));
        } else {
            logger.fine(String.format("Ignored %s event with null data.", type));
        }
    }

    @Override
    public Set<EventType> getSupportedEvents() {
        return null;
    }

    void addToBoundingBox(Rectangle rectangle) {
        if (boundingBox == null)
            boundingBox = rectangle.clone();
        else
            boundingBox = Rectangle.getCommonRectangle(boundingBox, rectangle);
    }

    Rectangle boundingBox = null;
    Logger logger = Logger.getLogger(MarginFinder.class.getName());
    static List<Vector> UNIT_SQUARE_CORNERS = Arrays.asList(new Vector(0,0,1), new Vector(1,0,1), new Vector(1,1,1), new Vector(0,1,1));
}

( MarginFinder.java )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...