【问题标题】:itext : merge pdfs and add stationary on each pageitext : 合并 pdf 并在每个页面上添加固定
【发布时间】:2017-03-24 18:28:06
【问题描述】:

我想将多个 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

=> 根据 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 章,但没有找到解决方案。

如果有人可以帮助我!

【问题讨论】:

  • “这就像文具的内容在每个页面都是重复的,而不是被重复使用” - 这正是代码的区别:在你的代码中使用PdfWriter你只使用一次getImportedPage(markReader, 1),在你的代码中使用PdfCopy你为每个页面调用getImportedPage(fdpReader, 1)
  • 我会回答@mkl
  • @Bruno 我要去。当我写评论时,我是通过智能手机在线的,在这样的设备上写完整的答案是相当痛苦的。

标签: java merge itext


【解决方案1】:

这就像文具的内容被复制到每个页面而不是被重复使用。

这是真的,它反映了 FusionPdfFusionPdf2 类之间的根本区别:

在前一个类中,您在开始时导入固定页面一次

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 中只包含一次固定页面的内容,您只需导入一次。

【讨论】:

  • 我在“羞辱我”、“laaaame”和“dumb-ass”之间犹豫不决......它会教我放弃未完成的开发......无论如何,谢谢你的帮助!跨度>
  • @SylvainP 如果答案对您有帮助,请接受(点击左侧的勾号)。
猜你喜欢
  • 2019-10-30
  • 1970-01-01
  • 2019-12-08
  • 2017-04-20
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 2015-12-02
相关资源
最近更新 更多