Java tutorial
package com.github.albfernandez.joinpdf; /* (C) Copyright 2014-2015 Alberto Fernndez <infjaf@gmail.com> This file is part of joinpdf. Foobar is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar. If not, see <http://www.gnu.org/licenses/>. */ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.apache.commons.lang3.StringUtils; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Image; import com.itextpdf.text.PageSize; import com.itextpdf.text.Rectangle; import com.itextpdf.text.io.RandomAccessSource; import com.itextpdf.text.io.RandomAccessSourceFactory; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfImportedPage; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.text.pdf.RandomAccessFileOrArray; import com.itextpdf.text.pdf.codec.TiffImage; public class JoinPdf { public static final Locale LOCALE_ES = new Locale("es", "ES"); private boolean extraCompression = false; private boolean crypt = false; private boolean printPageNumbers = false; private String metadataAuthor; private String metadataKeywords; private String metadataTitle; private String metadataSubject; private int actualPage = 0; private int totalPages = 0; private float margin = 25.0f; private List<File> files = new ArrayList<File>(); private static boolean bouncyCastleLoaded = false; static { try { Class.forName("org.bouncycastle.LICENSE"); Class.forName("org.bouncycastle.asn1.ASN1OctetString"); bouncyCastleLoaded = true; } catch (ClassNotFoundException e) { bouncyCastleLoaded = false; } } public JoinPdf() { super(); } public JoinPdf(final List<File> documentFilesFiles) { addFiles(documentFilesFiles); } public JoinPdf(final File dir) { addDir(dir); } public final void addDir(final File dir) { if (dir != null && dir.isDirectory()) { File[] documents = dir.listFiles(new JoinPdfFileFilter()); if (documents != null) { for (File document : documents) { addFile(document); } } } } public final void addFile(final File document) { if (document != null && document.canRead() && document.isFile()) { this.files.add(document); } } public final void addFiles(final List<File> documents) { for (File document : documents) { addFile(document); } } public final synchronized void export(final OutputStream os) throws Exception { checkParameters(); Document document = new Document(); try { if (isPrintPageNumbers()) { this.totalPages = gePageCount(); this.actualPage = 0; } PdfWriter writer = PdfWriter.getInstance(document, os); setParametersAndHeaders(writer, document); document.open(); for (File file : this.files) { add(file, document, writer); } } finally { ItextUtils.close(document); } } private void add(final File file, final Document document, final PdfWriter writer) throws Exception { String fileName = StringUtils.lowerCase(file.getName(), LOCALE_ES); if (fileName.endsWith(".tif") || fileName.endsWith(".tiff")) { addTiff(file, document, writer); } else if (fileName.endsWith(".pdf")) { addPdf(file, document, writer); } else { addImage(file, document, writer); } } private void addImage(final File file, final Document document, final PdfWriter writer) throws Exception { Image image = Image.getInstance(Files.readAllBytes(file.toPath())); addImage(image, document, writer); } private void addImage(final Image image, final Document document, final PdfWriter writer) throws Exception { if (image.getWidth() > image.getHeight()) { document.setPageSize(new Rectangle(PageSize.A4.getHeight(), PageSize.A4.getWidth())); } else { document.setPageSize(new Rectangle(PageSize.A4.getWidth(), PageSize.A4.getHeight())); } image.scaleToFit(document.getPageSize().getWidth() - this.margin * 2f, document.getPageSize().getHeight() - this.margin * 2f); float px = (document.getPageSize().getWidth() - image.getScaledWidth()) / 2f; float py = (document.getPageSize().getHeight() - image.getScaledHeight()) / 2f; image.setAbsolutePosition(px, py); document.newPage(); document.add(image); writePageNumber(writer); } private void writePageNumber(final PdfWriter writer) throws Exception { if (isPrintPageNumbers()) { writePageNumber(writer.getDirectContent()); } } private void writePageNumber(final PdfContentByte cb) throws DocumentException, IOException { if (isPrintPageNumbers()) { Rectangle size = cb.getPdfDocument().getPageSize(); BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); this.actualPage++; cb.beginText(); cb.setFontAndSize(bf, 9); cb.showTextAligned(PdfContentByte.ALIGN_CENTER, this.actualPage + " of " + this.totalPages, size.getWidth() / 2, 10, 0); cb.endText(); } } private void addPdf(final File file, final Document document, final PdfWriter writer) throws Exception { PdfReader pdfReader = null; try (InputStream is = new FileInputStream(file)) { pdfReader = new PdfReader(is); PdfContentByte cb = writer.getDirectContent(); for (int currentPage = 1; currentPage <= pdfReader.getNumberOfPages(); currentPage++) { Rectangle currentPageSize = pdfReader.getPageSize(currentPage); document.setPageSize(currentPageSize); document.newPage(); PdfImportedPage page = writer.getImportedPage(pdfReader, currentPage); cb.addTemplate(page, 0, 0); writePageNumber(cb); } writer.flush(); } finally { if (pdfReader != null) { writer.freeReader(pdfReader); ItextUtils.close(pdfReader); } } } private int gePageCount() throws IOException { int pages = 0; for (File file : this.files) { pages += getPageCount(file); } return pages; } private int getPageCount(final File file) throws IOException { String fileName = StringUtils.lowerCase(file.getName(), LOCALE_ES); if (fileName.endsWith(".tif") || fileName.endsWith(".tiff")) { return getPageCountTif(file); } if (fileName.endsWith(".pdf")) { return getPageCountPdf(file); } return 1; } private void addTiff(final File file, final Document document, final PdfWriter writer) throws Exception { RandomAccessSource source = createRamdomAccessSource(file); RandomAccessFileOrArray ramdomAccess = new RandomAccessFileOrArray(source); int pages = getPageCount(file); for (int i = 1; i <= pages; i++) { Image image = TiffImage.getTiffImage(ramdomAccess, i); addImage(image, document, writer); } } private static RandomAccessSource createRamdomAccessSource(final File file) throws IOException { RandomAccessSource source = new RandomAccessSourceFactory().setForceRead(false) .setUsePlainRandomAccess(Document.plainRandomAccess).createBestSource(file.getAbsolutePath()); return source; } public final void export(final File file) throws Exception { try (OutputStream os = new FileOutputStream(file)) { export(os); } } public final float getMargin() { return this.margin; } public final void setMargin(final float newMargin) { this.margin = newMargin; } public final boolean isExtraCompression() { return this.extraCompression; } public final void setExtraCompression(final boolean newExtraCompression) { this.extraCompression = newExtraCompression; } public final boolean isCrypt() { return this.crypt; } public final void setCrypt(final boolean newCrypt) { this.crypt = newCrypt; } public final boolean isPrintPageNumbers() { return this.printPageNumbers; } public final void setPrintPageNumbers(final boolean newPageNumbers) { this.printPageNumbers = newPageNumbers; } private void setParametersAndHeaders(final PdfWriter writer, final Document document) throws DocumentException { if (this.extraCompression) { writer.setFullCompression(); } if (this.isCrypt() && bouncyCastleLoaded) { int permisos = PdfWriter.ALLOW_PRINTING; writer.setEncryption(null, null, permisos, PdfWriter.ENCRYPTION_AES_128); } if (!StringUtils.isBlank(this.getMetadataAuthor())) { document.addAuthor(this.getMetadataAuthor()); } if (!StringUtils.isBlank(this.getMetadataKeywords())) { document.addKeywords(this.getMetadataKeywords()); } if (!StringUtils.isBlank(this.getMetadataTitle())) { document.addTitle(this.getMetadataTitle()); } if (!StringUtils.isBlank(this.getMetadataSubject())) { document.addSubject(this.getMetadataSubject()); } } private void checkParameters() throws Exception { if (this.files.isEmpty()) { throw new Exception("You must provide some files to join"); } if (this.isCrypt() && !bouncyCastleLoaded) { throw new Exception("Bouncycastle not found!"); } } public final String getMetadataAuthor() { return this.metadataAuthor; } public final void setMetadataAuthor(final String newMetadataAuthor) { this.metadataAuthor = newMetadataAuthor; } public final String getMetadataKeywords() { return this.metadataKeywords; } public final void setMetadataKeywords(final String newMetadataKeywords) { this.metadataKeywords = newMetadataKeywords; } public final String getMetadataTitle() { return this.metadataTitle; } public final void setMetadataTitle(final String newMetadataTitle) { this.metadataTitle = newMetadataTitle; } public final String getMetadataSubject() { return this.metadataSubject; } public final void setMetadataSubject(final String newMetadataSubject) { this.metadataSubject = newMetadataSubject; } public static int getPageCountTif(final File file) throws IOException { RandomAccessSource source = createRamdomAccessSource(file); RandomAccessFileOrArray ramdomAccess = new RandomAccessFileOrArray(source); return TiffImage.getNumberOfPages(ramdomAccess); } public static int getPageCountPdf(final byte[] contenido) { return getPageCountPdf(new ByteArrayInputStream(contenido)); } public static int getPageCountPdf(final File file) throws IOException { try (InputStream is = new FileInputStream(file)) { return getPageCountPdf(is); } } private static int getPageCountPdf(final InputStream is) { PdfReader pdfReader = null; try { pdfReader = new PdfReader(is); return pdfReader.getNumberOfPages(); } catch (Exception e) { return 0; } finally { ItextUtils.close(pdfReader); } } }