我正在使用Itext7。我有两个PDF。源PDF包含一些内容。目标PDF具有页眉和页脚。我需要将内容从源PDF添加到页面中间的目标PDF中,而不会重叠目标PDF的页眉和页脚。谁能帮我提供代码?
下面是我的代码,附件是源PDF的屏幕截图,需要将其嵌入final.pdf
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);
}
}
}
答案 0 :(得分:1)
首先,在您使用的某些构造背后的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助手insertIntoNithinTestFile
)
如果按原样使用原始源页面,则上面的代码将插入其中,包括所有页边距空间。如果您不希望这样做,而是减少其空间,则可以按照以下步骤确定页面内容的实际边界框,将页面缩小到该框,然后将其转发到上面的方法insertIntoNithinTestFile
,假设PdfDocument pdfDocument
的第1页将被处理:
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测试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));
}