2016-11-10 4 views
0

Я хотел бы объединить многократные pdf-файлы в новый pdf и добавить канцелярские принадлежности на каждую страницу.itext: слияние 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 результат был когда-то глючит. Ориентация не была keept. Тогда я нашел ответ, что поведение здесь function that can use iText to concatenate/merge pdfs together - causing some issues

=> По словам М. 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 книги, не найдя решение.

Если кто-нибудь может мне помочь!

+1

* «Это похоже на то, что содержимое канцелярских принадлежностей дублируется для каждой страницы, а не используется повторно» * - это как раз разница в коде: в вашем коде с использованием 'PdfWriter' вы используете' getImportedPage (markReader, 1) ' только один раз, в вашем коде с помощью 'PdfCopy' вы вызываете' getImportedPage (fdpReader, 1) 'для каждой страницы. – mkl

+0

Я бы сказал, что ответ @mkl –

+0

@Bruno Я собираюсь.Когда я написал комментарий, я был в сети через смартфон, и писать полные ответы здесь, на таких устройствах, довольно больно. – mkl

ответ

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 только один раз вам нужно импортировать его только один раз.

+0

Я колеблюсь между: «стыд за меня», «laaaame» и «dumb-ass». Это научит меня отказаться от незавершенного ... В любом случае спасибо вам за помощь! – SylvainP

+0

@SylvainP Если ответ вам помог, пожалуйста, примите его (нажмите галочку слева). – mkl

+0

@ mkl Я забыл! спасибо – SylvainP

Смежные вопросы