Java tutorial
package com.fangxin365.core.utils; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSInteger; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.cos.COSNumber; import org.apache.pdfbox.cos.COSStream; import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import org.apache.pdfbox.pdmodel.PDDocumentInformation; import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.COSArrayList; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline; import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.apache.pdfbox.pdmodel.interactive.form.PDFieldFactory; import org.apache.pdfbox.util.PDFCloneUtility; /** * This class will take a list of pdf documents and merge them, saving the * result in a new document. * * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a> * @version $Revision: 1.3 $ */ public class PDFMerger { private List<InputStream> sources; private String destinationFileName; private OutputStream destinationStream; private boolean ignoreAcroFormErrors = false; /** * Instantiate a new PDFMergerUtility. */ public PDFMerger() { sources = new ArrayList<InputStream>(); } /** * Get the name of the destination file. * * @return Returns the destination. */ public String getDestinationFileName() { return destinationFileName; } /** * Set the name of the destination file. * * @param destination * The destination to set. */ public void setDestinationFileName(String destination) { this.destinationFileName = destination; } /** * Get the destination OutputStream. * * @return Returns the destination OutputStream. */ public OutputStream getDestinationStream() { return destinationStream; } /** * Set the destination OutputStream. * * @param destStream * The destination to set. */ public void setDestinationStream(OutputStream destStream) { destinationStream = destStream; } /** * Add a source file to the list of files to merge. * * @param source * Full path and file name of source document. */ public void addSource(String source) { try { sources.add(new FileInputStream(new File(source))); } catch (Exception e) { throw new RuntimeException(e); } } /** * Add a source file to the list of files to merge. * * @param source * File representing source document */ public void addSource(File source) { try { sources.add(new FileInputStream(source)); } catch (Exception e) { throw new RuntimeException(e); } } /** * Add a source to the list of documents to merge. * * @param source * InputStream representing source document */ public void addSource(InputStream source) { sources.add(source); } /** * Add a list of sources to the list of documents to merge. * * @param sourcesList * List of InputStream objects representing source documents */ public void addSources(List<InputStream> sourcesList) { this.sources.addAll(sourcesList); } /** * Merge the list of source documents, saving the result in the destination * file. * * @throws IOException * If there is an error saving the document. * @throws COSVisitorException * If an error occurs while saving the destination file. */ public void mergeDocuments() throws IOException, COSVisitorException { PDDocument destination = null; InputStream sourceFile; PDDocument source; if (sources != null && sources.size() > 0) { java.util.Vector<PDDocument> tobeclosed = new java.util.Vector<PDDocument>(); try { Iterator<InputStream> sit = sources.iterator(); sourceFile = sit.next(); destination = PDDocument.load(sourceFile); while (sit.hasNext()) { sourceFile = sit.next(); source = PDDocument.load(sourceFile); tobeclosed.add(source); appendDocument(destination, source); } if (destinationStream == null) { destination.save(destinationFileName); } else { destination.save(destinationStream); } } finally { if (destination != null) { destination.close(); } for (PDDocument doc : tobeclosed) { doc.close(); } } } } /** * append all pages from source to destination. * * @param destination * the document to receive the pages * @param source * the document originating the new pages * * @throws IOException * If there is an error accessing data from either document. */ public void appendDocument(PDDocument destination, PDDocument source) throws IOException { if (destination.isEncrypted()) { System.out.println("Error: destination PDF is encrypted, can't append encrypted PDF documents."); } if (source.isEncrypted()) { System.out.println("Error: source PDF is encrypted, can't append encrypted PDF documents."); } PDDocumentInformation destInfo = destination.getDocumentInformation(); PDDocumentInformation srcInfo = source.getDocumentInformation(); destInfo.getDictionary().mergeInto(srcInfo.getDictionary()); PDDocumentCatalog destCatalog = destination.getDocumentCatalog(); PDDocumentCatalog srcCatalog = source.getDocumentCatalog(); // use the highest version number for the resulting pdf float destVersion = destination.getDocument().getVersion(); float srcVersion = source.getDocument().getVersion(); if (destVersion < srcVersion) { destination.getDocument().setVersion(srcVersion); } if (destCatalog.getOpenAction() == null) { destCatalog.setOpenAction(srcCatalog.getOpenAction()); } // maybe there are some shared resources for all pages COSDictionary srcPages = (COSDictionary) srcCatalog.getCOSDictionary().getDictionaryObject(COSName.PAGES); COSDictionary srcResources = (COSDictionary) srcPages.getDictionaryObject(COSName.RESOURCES); COSDictionary destPages = (COSDictionary) destCatalog.getCOSDictionary().getDictionaryObject(COSName.PAGES); COSDictionary destResources = (COSDictionary) destPages.getDictionaryObject(COSName.RESOURCES); if (srcResources != null) { if (destResources != null) { destResources.mergeInto(srcResources); } else { destPages.setItem(COSName.RESOURCES, srcResources); } } PDFCloneUtility cloner = new PDFCloneUtility(destination); try { PDAcroForm destAcroForm = destCatalog.getAcroForm(); PDAcroForm srcAcroForm = srcCatalog.getAcroForm(); if (destAcroForm == null) { cloner.cloneForNewDocument(srcAcroForm); destCatalog.setAcroForm(srcAcroForm); } else { if (srcAcroForm != null) { mergeAcroForm(cloner, destAcroForm, srcAcroForm); } } } catch (Exception e) { // if we are not ignoring exceptions, we'll re-throw this if (!ignoreAcroFormErrors) { throw (IOException) e; } } COSArray destThreads = (COSArray) destCatalog.getCOSDictionary().getDictionaryObject(COSName.THREADS); COSArray srcThreads = (COSArray) cloner .cloneForNewDocument(destCatalog.getCOSDictionary().getDictionaryObject(COSName.THREADS)); if (destThreads == null) { destCatalog.getCOSDictionary().setItem(COSName.THREADS, srcThreads); } else { destThreads.addAll(srcThreads); } PDDocumentNameDictionary destNames = destCatalog.getNames(); PDDocumentNameDictionary srcNames = srcCatalog.getNames(); if (srcNames != null) { if (destNames == null) { destCatalog.getCOSDictionary().setItem(COSName.NAMES, cloner.cloneForNewDocument(srcNames)); } else { cloner.cloneMerge(srcNames, destNames); } } PDDocumentOutline destOutline = destCatalog.getDocumentOutline(); PDDocumentOutline srcOutline = srcCatalog.getDocumentOutline(); if (srcOutline != null) { if (destOutline == null) { PDDocumentOutline cloned = new PDDocumentOutline( (COSDictionary) cloner.cloneForNewDocument(srcOutline)); destCatalog.setDocumentOutline(cloned); } else { PDOutlineItem first = srcOutline.getFirstChild(); if (first != null) { PDOutlineItem clonedFirst = new PDOutlineItem( (COSDictionary) cloner.cloneForNewDocument(first)); destOutline.appendChild(clonedFirst); } } } String destPageMode = destCatalog.getPageMode(); String srcPageMode = srcCatalog.getPageMode(); if (destPageMode == null) { destCatalog.setPageMode(srcPageMode); } COSDictionary destLabels = (COSDictionary) destCatalog.getCOSDictionary() .getDictionaryObject(COSName.PAGE_LABELS); COSDictionary srcLabels = (COSDictionary) srcCatalog.getCOSDictionary() .getDictionaryObject(COSName.PAGE_LABELS); if (srcLabels != null) { int destPageCount = destination.getNumberOfPages(); COSArray destNums = null; if (destLabels == null) { destLabels = new COSDictionary(); destNums = new COSArray(); destLabels.setItem(COSName.NUMS, destNums); destCatalog.getCOSDictionary().setItem(COSName.PAGE_LABELS, destLabels); } else { destNums = (COSArray) destLabels.getDictionaryObject(COSName.NUMS); } COSArray srcNums = (COSArray) srcLabels.getDictionaryObject(COSName.NUMS); if (srcNums != null) { for (int i = 0; i < srcNums.size(); i += 2) { COSNumber labelIndex = (COSNumber) srcNums.getObject(i); long labelIndexValue = labelIndex.intValue(); destNums.add(COSInteger.get(labelIndexValue + destPageCount)); destNums.add(cloner.cloneForNewDocument(srcNums.getObject(i + 1))); } } } COSStream destMetadata = (COSStream) destCatalog.getCOSDictionary().getDictionaryObject(COSName.METADATA); COSStream srcMetadata = (COSStream) srcCatalog.getCOSDictionary().getDictionaryObject(COSName.METADATA); if (destMetadata == null && srcMetadata != null) { PDStream newStream = new PDStream(destination, srcMetadata.getUnfilteredStream(), false); newStream.getStream().mergeInto(srcMetadata); newStream.addCompression(); destCatalog.getCOSDictionary().setItem(COSName.METADATA, newStream); } // finally append the pages @SuppressWarnings("unchecked") List<PDPage> pages = srcCatalog.getAllPages(); Iterator<PDPage> pageIter = pages.iterator(); while (pageIter.hasNext()) { PDPage page = pageIter.next(); PDPage newPage = new PDPage((COSDictionary) cloner.cloneForNewDocument(page.getCOSDictionary())); newPage.setCropBox(page.findCropBox()); newPage.setMediaBox(page.findMediaBox()); newPage.setRotation(page.findRotation()); destination.addPage(newPage); } } private int nextFieldNum = 1; /** * Merge the contents of the source form into the destination form for the * destination file. * * @param cloner * the object cloner for the destination document * @param destAcroForm * the destination form * @param srcAcroForm * the source form * @throws IOException * If an error occurs while adding the field. */ @SuppressWarnings({ "rawtypes", "unchecked" }) private void mergeAcroForm(PDFCloneUtility cloner, PDAcroForm destAcroForm, PDAcroForm srcAcroForm) throws IOException { List destFields = destAcroForm.getFields(); List srcFields = srcAcroForm.getFields(); if (srcFields != null) { if (destFields == null) { destFields = new COSArrayList(); destAcroForm.setFields(destFields); } Iterator srcFieldsIterator = srcFields.iterator(); while (srcFieldsIterator.hasNext()) { PDField srcField = (PDField) srcFieldsIterator.next(); PDField destField = PDFieldFactory.createField(destAcroForm, (COSDictionary) cloner.cloneForNewDocument(srcField.getDictionary())); // if the form already has a field with this name then we need // to rename this field // to prevent merge conflicts. if (destAcroForm.getField(destField.getFullyQualifiedName()) != null) { destField.setPartialName("dummyFieldName" + (nextFieldNum++)); } destFields.add(destField); } } } public boolean isIgnoreAcroFormErrors() { return ignoreAcroFormErrors; } public void setIgnoreAcroFormErrors(boolean ignoreAcroFormErrors) { this.ignoreAcroFormErrors = ignoreAcroFormErrors; } public static void main(String[] args) throws Exception { PDFMerger merger = new PDFMerger(); merger.addSource( new File("E:/Work/Java/WebAdmin/dist/webapp/upload/html/product/report/FX0201010100Y0007SH2C.pdf")); //merger.addSource(new File("E:/Work/Java/WebAdmin/dist/webapp/upload/html/product/report/FX0201010100Y0007yumiyouzhengjiwan_nongcanyixiang.pdf")); merger.addSource(new File( "E:/Work/Java/WebAdmin/dist/webapp/upload/html/product/report/FX1001000000Y0003JiDan??.pdf")); merger.setDestinationFileName("E:/Work/b.pdf"); merger.mergeDocuments(); } }