我想将多个pdf合并为一个新的pdf并在每个页面上添加信纸。
为此我像这样使用PdfWriter:
public class FusionPdf extends PdfPageEventHelper {
private Document document = null;
private PdfWriter writer = null;
private PdfReader markReader = null;
private PdfImportedPage fondDePage = null;
private String textFili = null;
private String textMark = null;
private static final Font FONT1 = FontFactory.getFont(FontFactory.HELVETICA, 50, Font.NORMAL, new GrayColor(0.7f));
private static final Font FONT2 = FontFactory.getFont(FontFactory.HELVETICA, 6, Font.NORMAL, BaseColor.BLACK);
/**
* liste des fichiers � concatener
*/
private List<File> pdfsOriginaux = new ArrayList<File>();
/**
*
* @param pdfDestination fichier de pdf de destination
* @param pdfsOriginaux fichiers pdf � concatener
* @param pdfTatoueur Fond de page (peut �tre null)
* @param textFiligrane filigran (peut �tre null)
* @throws IOException
* @throws DocumentException
* @throws Exception
*/
public FusionPdf(File pdfDestination, List<File> pdfsOriginaux, File pdfTatoueur, String textFiligrane, String textMarquage) throws DocumentException, IOException {
if (pdfsOriginaux.isEmpty()){
throw new IOException("Aucun document pdf a traiter !");
}
this.pdfsOriginaux = pdfsOriginaux;
this.init(pdfDestination, pdfTatoueur, textFiligrane, textMarquage);
}
/**
*
* @param pdfDestination fichier de pdf de destination
* @param pdfOriginal fichier pdf a traiter
* @param pdfTatoueur Fond de page (peut etre null)
* @param textFiligrane filigrane (peut etre null)
* @param textMarquage note technique en haut à droite en petit (peut etre null)
* @throws IOException
* @throws DocumentException
* @throws Exception
*/
public FusionPdf(File pdfDestination, File pdfOriginal, File pdfTatoueur, String textFiligrane, String textMarquage) throws DocumentException, IOException {
this.pdfsOriginaux.add(pdfOriginal);
this.init(pdfDestination, pdfTatoueur, textFiligrane, textMarquage);
}
/**
* initialisation des attributs
*
* @param pdfDestination
* @param pdfTatoueur
* @param textFiligrane
* @throws DocumentException
* @throws IOException
*/
private void init(File pdfDestination, File pdfTatoueur, String textFiligrane, String textMarquage) throws DocumentException, IOException{
document = new Document();
writer = PdfWriter.getInstance(document, new FileOutputStream(pdfDestination));
writer.setPageEvent(this);
if (pdfTatoueur != null) {
markReader = new PdfReader(pdfTatoueur.getAbsolutePath());
fondDePage = writer.getImportedPage(markReader, 1);
}
if (textFiligrane != null) {
textFili = textFiligrane;
}
if (textFiligrane != null) {
textMark = textMarquage;
}
}
/**
* applique la concatenation et la fusion
* @throws IOException
*/
public void fuse() throws IOException{
//---->initialisation d'un flux vers le pdf
PdfReader originalReader = new PdfReader(pdfsOriginaux.get(0).getAbsolutePath());
document.open();
for (File pdfOriginal : pdfsOriginaux) {
originalReader = new PdfReader(pdfOriginal.getAbsolutePath());
for (int i = 1; i <= originalReader.getNumberOfPages(); i++) {
document.setPageSize(originalReader.getPageSizeWithRotation(i));
document.newPage();
writer.getDirectContent().addTemplate(writer.getImportedPage(originalReader, i), 0, 0);
}
}
document.close();
originalReader.close();
if (markReader != null) {
markReader.close();
}
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfContentByte directContent;
Rectangle docPageSize = document.getPageSize();
//ajout du fond de page
if (markReader != null) {
directContent = writer.getDirectContentUnder();
Rectangle markPageSize = markReader.getPageSize(1);
float hScale = docPageSize.getWidth() / markPageSize.getWidth();
float vScale = docPageSize.getHeight() / markPageSize.getHeight();
float markScale = (hScale< vScale) ? hScale : vScale;
float hTrans = (float)((docPageSize.getWidth()-markPageSize.getWidth()* markScale) / 2.0);
float vTrans = (float)((docPageSize.getHeight()-markPageSize.getHeight()* markScale) / 2.0);
directContent.addTemplate(fondDePage, markScale, 0, 0, markScale, hTrans, vTrans );
}
//ajout du filigrane
if (textFili != null) {
directContent = writer.getDirectContent();
PdfGState gstate = new PdfGState();
gstate.setFillOpacity(0.3f);
gstate.setStrokeOpacity(0.3f);
directContent.saveState();
directContent.setGState(gstate);
ColumnText.showTextAligned(directContent,Element.ALIGN_CENTER, new Phrase(textFili, FONT1), docPageSize.getWidth()/2, docPageSize.getHeight()/2, 45);
directContent.restoreState();
}
//ajout de la marque en haut à droite en petit
if (textMark != null) {
directContent = writer.getDirectContent();
PdfGState gstate = new PdfGState();
directContent.saveState();
directContent.setGState(gstate);
ColumnText.showTextAligned(directContent,Element.ALIGN_RIGHT, new Phrase(textMark, FONT2), docPageSize.getWidth()-3, docPageSize.getHeight()-8, 0);
directContent.restoreState();
}
}
}
但这是错误的:取决于原始pdf,结果有时是错误的。 方向不是保持。 然后我在这里找到了这种行为的答案 function that can use iText to concatenate / merge pdfs together - causing some issues
=&GT;据M. Lowagie说,我必须使用PdfCopy而不是PdfWriter。 然后我做了这个代码:
public class FusionPdf2 extends PdfPageEventHelper {
private static final Font FONT1 = FontFactory.getFont(FontFactory.HELVETICA, 50, Font.NORMAL, new GrayColor(0.7f));
private static final Font FONT2 = FontFactory.getFont(FontFactory.HELVETICA, 6, Font.NORMAL, BaseColor.BLACK);
private List<File> pdfsOriginaux = new ArrayList<File>();
private File pdfDestination = null;
private File pdfTatoueur = null;
private String textFiligrane = null;
private String textMarquage = null;
/**
*
* @param pdfDestination fichier de pdf de destination
* @param pdfsOriginaux fichiers pdf à concatener
* @param pdfTatoueur Fond de page (peut être null)
* @param textFiligrane filigran (peut être null)
* @throws IOException
* @throws DocumentException
* @throws Exception
*/
public FusionPdf2(File pdfDestination, List<File> pdfsOriginaux, File pdfTatoueur, String textFiligrane, String textMarquage) throws DocumentException, IOException {
this.pdfDestination = pdfDestination;
if (pdfsOriginaux.isEmpty()){
throw new IOException("Aucun document pdf a traiter !");
}
this.pdfsOriginaux = pdfsOriginaux;
this.pdfTatoueur = pdfTatoueur;
this.textFiligrane = textFiligrane;
this.textMarquage = textMarquage;
}
/**
*
* @param pdfDestination fichier de pdf de destination
* @param pdfOriginal fichier pdf a traiter
* @param pdfTatoueur Fond de page (peut etre null)
* @param textFiligrane filigrane (peut etre null)
* @param textMarquage note technique en haut à droite en petit (peut etre null)
* @throws IOException
* @throws DocumentException
* @throws Exception
*/
public FusionPdf2(File pdfDestination, File pdfOriginal, File pdfTatoueur, String textFiligrane, String textMarquage) throws DocumentException, IOException {
this.pdfDestination = pdfDestination;
this.pdfsOriginaux.add(pdfOriginal);
this.pdfTatoueur = pdfTatoueur;
this.textFiligrane = textFiligrane;
this.textMarquage = textMarquage;
}
/**
* applique la concatenation et la fusion
*
* @param pdfDestination
* @param pdfTatoueur
* @param textFiligrane
* @throws DocumentException
* @throws IOException
* @throws IOException
* @throws DocumentException
*/
public void fuse() throws IOException, DocumentException{
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(pdfDestination));
document.open();
PdfReader originalReader;
PdfReader fdpReader = null;
if (pdfTatoueur != null) {
fdpReader = new PdfReader(pdfTatoueur.getAbsolutePath());
}
for (File pdfOriginal : pdfsOriginaux) {
originalReader = new PdfReader(pdfOriginal.getAbsolutePath());
for (int i = 0 ; i < originalReader.getNumberOfPages(); ) {
PdfImportedPage page = copy.getImportedPage(originalReader, ++i);
PageStamp stamp = copy.createPageStamp(page);
Rectangle docPageSize = originalReader.getPageSizeWithRotation(i);
//ajout du fond de page
if (pdfTatoueur != null) {
PdfImportedPage fondDePage = copy.getImportedPage(fdpReader, 1);
PdfContentByte directContent = stamp.getUnderContent();
Rectangle markPageSize = fdpReader.getPageSize(1);
float hScale = docPageSize.getWidth() / markPageSize.getWidth();
float vScale = docPageSize.getHeight() / markPageSize.getHeight();
float markScale = (hScale< vScale) ? hScale : vScale;
float hTrans = (float)((docPageSize.getWidth()-markPageSize.getWidth()* markScale) / 2.0);
float vTrans = (float)((docPageSize.getHeight()-markPageSize.getHeight()* markScale) / 2.0);
directContent.addTemplate(fondDePage, markScale, 0, 0, markScale, hTrans, vTrans );
}
//ajout du filigrane
if (StringUtils.isNotBlank(textFiligrane)) {
PdfContentByte directContent = stamp.getOverContent();
PdfGState gstate = new PdfGState();
gstate.setFillOpacity(0.3f);
gstate.setStrokeOpacity(0.3f);
directContent.saveState();
directContent.setGState(gstate);
ColumnText.showTextAligned(directContent,Element.ALIGN_CENTER, new Phrase(textFiligrane, FONT1), docPageSize.getWidth()/2, docPageSize.getHeight()/2, 45);
directContent.restoreState();
}
//ajout de la marque en haut à droite en petit
if (StringUtils.isNotBlank(textMarquage)) {
PdfContentByte directContent = stamp.getOverContent();
ColumnText.showTextAligned(directContent,Element.ALIGN_RIGHT, new Phrase(textMarquage, FONT2), docPageSize.getWidth()-3, docPageSize.getHeight()-8, 0);
}
stamp.alterContents();
copy.addPage(page);
}
if (originalReader!=null) {
originalReader.close();
}
}
document.close();
}
}
这次在任何情况下结果都很好:所有页面都处于良好的方向。
但是,制作的pdf大约是前一代码的10倍。 经过分析,我发现了原因:在我添加文具之前一切都很好。
就像每个页面都重复了文具的内容而不是重复使用。
显然我再次做错了。 在没有找到解决方案的情况下,我阅读了本书的第6章。
如果有人可以帮助我!
答案 0 :(得分:0)
就像每个页面都重复了文具的内容而不是重复使用。
这是真的,它反映了您的FusionPdf
和FusionPdf2
类之间的根本区别:
在前一课中,您可以在开头导入固定页面
private void init(File pdfDestination, File pdfTatoueur, String textFiligrane, String textMarquage) throws DocumentException, IOException{
[...]
if (pdfTatoueur != null) {
markReader = new PdfReader(pdfTatoueur.getAbsolutePath());
fondDePage = writer.getImportedPage(markReader, 1);
}
[...]
}
并反复重复使用此导入的页面:
public void onEndPage(PdfWriter writer, Document document) {
[...]
//ajout du fond de page
if (markReader != null) {
[...]
directContent.addTemplate(fondDePage, markScale, 0, 0, markScale, hTrans, vTrans );
}
[...]
}
另一方面,在后一类中,您反复导入固定页面,每页应用一次:
for (int i = 0 ; i < originalReader.getNumberOfPages(); ) {
[...]
if (pdfTatoueur != null) {
PdfImportedPage fondDePage = copy.getImportedPage(fdpReader, 1);
[...]
directContent.addTemplate(fondDePage, markScale, 0, 0, markScale, hTrans, vTrans );
}
[...]
}
要将结果PDF中固定页面的内容只有一次,您只需要导入一次。