I cannot use the getInstance() method of the PdfWriter class nor can I use the open() method of the document...how do I fix?
I have iText package 7.1.3.
My code is as below:
PdfWriter.class.getConstructor(document, new FileOutputStream(FILE));
document.open();
I am converting an image to pdf btw
This is the basic demonstration of code picked from tutorialspoint, hope this will helps you.
// Creating a PdfWriter
String dest = "C:/hellodearcode/imgtest.pdf";
PdfWriter writer = new PdfWriter(dest);
// Creating a PdfDocument
PdfDocument pdfDoc = new PdfDocument(writer);
// Creating a Document OBJECT
document = new Document(pdfDoc);
// Creating an ImageData object
String imageFile = "C:/hellodearcode/tabishrana-blog.jpg";
ImageData data = ImageDataFactory.create(imageFile);
// Creating an Image object
Image img = new Image(data);
// close document
document.close();
you should follow this object creation flow to make a successful call
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
public class AddingImage {
public static void main(String args[]) throws Exception {
// Creating a PdfWriter
String dest = "C:/itextExamples/addingImage.pdf";
PdfWriter writer = new PdfWriter(dest);
// Creating a PdfDocument
PdfDocument pdf = new PdfDocument(writer);
// Creating a Document
Document document = new Document(pdf);
// Creating an ImageData object
String imFile = "C:/itextExamples/logo.jpg";
ImageData data = ImageDataFactory.create(imFile);
// Creating an Image object
Image image = new Image(data);
// Adding image to the document
document.add(image);
// Closing the document
document.close();
System.out.println("Image added");
}
}
Related
I have a PDF document with fillable fields; I need to resave it without them. I have tried to do it the following way:
public static void main(String[] args) throws IOException {
PdfReader reader = new PdfReader(Objects.requireNonNull(Main.class.getClassLoader().getResourceAsStream("FillableFields.pdf")));
ByteArrayOutputStream os = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(os);
PdfDocument document = new PdfDocument(reader, writer);
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(document, true);
acroForm.flattenFields();
document.close();
Files.write(Paths.get("WithoutFields.pdf"), os.toByteArray(), StandardOpenOption.CREATE);
}
This approach is not suitable for me because the values from these fields stay in the document, but I need to remove all data (fields and their values).
Then I tried to do it the next way:
public static void main(String[] args) throws IOException {
PdfReader reader = new PdfReader(Objects.requireNonNull(Main.class.getClassLoader().getResourceAsStream("FillableFields.pdf")));
ByteArrayOutputStream os = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(os);
PdfDocument document = new PdfDocument(reader, writer);
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(document, true);
if(acroForm.hasXfaForm())
acroForm.removeXfaForm();
document.close();
System.out.println(os.size());
Files.write(Paths.get("WithoutFields.pdf"), os.toByteArray(), StandardOpenOption.CREATE);
}
It is also not suitable for me because the condition if(acroForm.hasXfaForm()) has returned false.
Can anyone suggest to me how can I save a PDF without fillable fields and their values?
I am using iTextPdf for appending data to pdf but I want to save the modified file to a File object so that I can send that file to client server.
Code :
package doc;
import java.io.FileOutputStream;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
public class Doc_demo {
public static void main(String args[]){
try {
//Create PdfReader instance.
PdfReader pdfReader =
new PdfReader("C:\\Users\\user1\\iTextPDFSamples\\user1\\SAMPLE_A071W471.pdf");
//Create PdfStamper instance.
PdfStamper pdfStamper = new PdfStamper(pdfReader,
new FileOutputStream("C:\\Users\\user1\\iTextPDFSamples\\user1\\ModifiedTestFile.pdf"));
//Create BaseFont instance.
BaseFont baseFont = BaseFont.createFont(
BaseFont.TIMES_ROMAN,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
//Get the number of pages in pdf.
int pages = pdfReader.getNumberOfPages();
//Iterate the pdf through pages.
for(int i=1; i<=1; i++) { //i<=pages
//Contain the pdf data.
PdfContentByte pageContentByte =
pdfStamper.getOverContent(i);
//Set text font and size.
pageContentByte.setFontAndSize(baseFont, 8);
pageContentByte.beginText();
pageContentByte.setTextMatrix(379, 615);
pageContentByte.showText("SN01234567890");
pageContentByte.endText();
pageContentByte.beginText();
pageContentByte.setTextMatrix(450, 615);
pageContentByte.showText("European Union");
pageContentByte.endText();
}
//Close the pdfStamper.
pdfStamper.close();
System.out.println("PDF modified successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Code works fine.
pdfStamper.close(); this line will save the modified file to the given location but how to convert it to File object.
Solved the issue :
File tempFile = File.createTempFile("Tempfile",".pdf");
created one tempfile and used this tempfile for pdfstamper's
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(tempFile));
This solved the issue.
I want to merge many PDF files into one using PDFBox and this is what I've done:
PDDocument document = new PDDocument();
for (String pdfFile: pdfFiles) {
PDDocument part = PDDocument.load(pdfFile);
List<PDPage> list = part.getDocumentCatalog().getAllPages();
for (PDPage page: list) {
document.addPage(page);
}
part.close();
}
document.save("merged.pdf");
document.close();
Where pdfFiles is an ArrayList<String> containing all the PDF files.
When I'm running the above, I'm always getting:
org.apache.pdfbox.exceptions.COSVisitorException: Bad file descriptor
Am I doing something wrong? Is there any other way of doing it?
Why not use the PDFMergerUtility of pdfbox?
PDFMergerUtility ut = new PDFMergerUtility();
ut.addSource(...);
ut.addSource(...);
ut.addSource(...);
ut.setDestinationFileName(...);
ut.mergeDocuments();
A quick Google search returned this bug: "Bad file descriptor while saving a document w. imported PDFs".
It looks like you need to keep the PDFs to be merged open, until after you have saved and closed the combined PDF.
This is a ready to use code, merging four pdf files with itext.jar from http://central.maven.org/maven2/com/itextpdf/itextpdf/5.5.0/itextpdf-5.5.0.jar, more on http://tutorialspointexamples.com/
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
/**
* This class is used to merge two or more
* existing pdf file using iText jar.
*/
public class PDFMerger {
static void mergePdfFiles(List<InputStream> inputPdfList,
OutputStream outputStream) throws Exception{
//Create document and pdfReader objects.
Document document = new Document();
List<PdfReader> readers =
new ArrayList<PdfReader>();
int totalPages = 0;
//Create pdf Iterator object using inputPdfList.
Iterator<InputStream> pdfIterator =
inputPdfList.iterator();
// Create reader list for the input pdf files.
while (pdfIterator.hasNext()) {
InputStream pdf = pdfIterator.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages = totalPages + pdfReader.getNumberOfPages();
}
// Create writer for the outputStream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
//Open document.
document.open();
//Contain the pdf data.
PdfContentByte pageContentByte = writer.getDirectContent();
PdfImportedPage pdfImportedPage;
int currentPdfReaderPage = 1;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Iterate and process the reader list.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
//Create page and add content.
while (currentPdfReaderPage <= pdfReader.getNumberOfPages()) {
document.newPage();
pdfImportedPage = writer.getImportedPage(
pdfReader,currentPdfReaderPage);
pageContentByte.addTemplate(pdfImportedPage, 0, 0);
currentPdfReaderPage++;
}
currentPdfReaderPage = 1;
}
//Close document and outputStream.
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Pdf files merged successfully.");
}
public static void main(String args[]){
try {
//Prepare input pdf file list as list of input stream.
List<InputStream> inputPdfList = new ArrayList<InputStream>();
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_1.pdf"));
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_2.pdf"));
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_3.pdf"));
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_4.pdf"));
//Prepare output stream for merged pdf file.
OutputStream outputStream =
new FileOutputStream("..\\pdf\\MergeFile_1234.pdf");
//call method to merge pdf files.
mergePdfFiles(inputPdfList, outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Multiple pdf merged method using org.apache.pdfbox:
public void mergePDFFiles(List<File> files,
String mergedFileName) {
try {
PDFMergerUtility pdfmerger = new PDFMergerUtility();
for (File file : files) {
PDDocument document = PDDocument.load(file);
pdfmerger.setDestinationFileName(mergedFileName);
pdfmerger.addSource(file);
pdfmerger.mergeDocuments(MemoryUsageSetting.setupTempFileOnly());
document.close();
}
} catch (IOException e) {
logger.error("Error to merge files. Error: " + e.getMessage());
}
}
From main program, call mergePDFFiles method using list of files and target file name.
String mergedFileName = "Merged.pdf";
mergePDFFiles(files, mergedFileName);
After calling mergePDFFiles, load merged file
File mergedFile = new File(mergedFileName);
package article14;
import java.io.File;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.util.PDFMergerUtility;
public class Pdf
{
public static void main(String args[])
{
new Pdf().createNew();
new Pdf().combine();
}
public void combine()
{
try
{
PDFMergerUtility mergePdf = new PDFMergerUtility();
String folder ="pdf";
File _folder = new File(folder);
File[] filesInFolder;
filesInFolder = _folder.listFiles();
for (File string : filesInFolder)
{
mergePdf.addSource(string);
}
mergePdf.setDestinationFileName("Combined.pdf");
mergePdf.mergeDocuments();
}
catch(Exception e)
{
}
}
public void createNew()
{
PDDocument document = null;
try
{
String filename="test.pdf";
document=new PDDocument();
PDPage blankPage = new PDPage();
document.addPage( blankPage );
document.save( filename );
}
catch(Exception e)
{
}
}
}
If you want to combine two files where one overlays the other (example: document A is a template and document B has the text you want to put on the template), this works:
after creating "doc", you want to write your template (templateFile) on top of that -
PDDocument watermarkDoc = PDDocument.load(getServletContext()
.getRealPath(templateFile));
Overlay overlay = new Overlay();
overlay.overlay(watermarkDoc, doc);
Using iText (existing PDF in bytes)
public static byte[] mergePDF(List<byte[]> pdfFilesAsByteArray) throws DocumentException, IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
Document document = null;
PdfCopy writer = null;
for (byte[] pdfByteArray : pdfFilesAsByteArray) {
try {
PdfReader reader = new PdfReader(pdfByteArray);
int numberOfPages = reader.getNumberOfPages();
if (document == null) {
document = new Document(reader.getPageSizeWithRotation(1));
writer = new PdfCopy(document, outStream); // new
document.open();
}
PdfImportedPage page;
for (int i = 0; i < numberOfPages;) {
++i;
page = writer.getImportedPage(reader, i);
writer.addPage(page);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
document.close();
outStream.close();
return outStream.toByteArray();
}
I want to merge many PDF files into one using PDFBox and this is what I've done:
PDDocument document = new PDDocument();
for (String pdfFile: pdfFiles) {
PDDocument part = PDDocument.load(pdfFile);
List<PDPage> list = part.getDocumentCatalog().getAllPages();
for (PDPage page: list) {
document.addPage(page);
}
part.close();
}
document.save("merged.pdf");
document.close();
Where pdfFiles is an ArrayList<String> containing all the PDF files.
When I'm running the above, I'm always getting:
org.apache.pdfbox.exceptions.COSVisitorException: Bad file descriptor
Am I doing something wrong? Is there any other way of doing it?
Why not use the PDFMergerUtility of pdfbox?
PDFMergerUtility ut = new PDFMergerUtility();
ut.addSource(...);
ut.addSource(...);
ut.addSource(...);
ut.setDestinationFileName(...);
ut.mergeDocuments();
A quick Google search returned this bug: "Bad file descriptor while saving a document w. imported PDFs".
It looks like you need to keep the PDFs to be merged open, until after you have saved and closed the combined PDF.
This is a ready to use code, merging four pdf files with itext.jar from http://central.maven.org/maven2/com/itextpdf/itextpdf/5.5.0/itextpdf-5.5.0.jar, more on http://tutorialspointexamples.com/
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
/**
* This class is used to merge two or more
* existing pdf file using iText jar.
*/
public class PDFMerger {
static void mergePdfFiles(List<InputStream> inputPdfList,
OutputStream outputStream) throws Exception{
//Create document and pdfReader objects.
Document document = new Document();
List<PdfReader> readers =
new ArrayList<PdfReader>();
int totalPages = 0;
//Create pdf Iterator object using inputPdfList.
Iterator<InputStream> pdfIterator =
inputPdfList.iterator();
// Create reader list for the input pdf files.
while (pdfIterator.hasNext()) {
InputStream pdf = pdfIterator.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages = totalPages + pdfReader.getNumberOfPages();
}
// Create writer for the outputStream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
//Open document.
document.open();
//Contain the pdf data.
PdfContentByte pageContentByte = writer.getDirectContent();
PdfImportedPage pdfImportedPage;
int currentPdfReaderPage = 1;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Iterate and process the reader list.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
//Create page and add content.
while (currentPdfReaderPage <= pdfReader.getNumberOfPages()) {
document.newPage();
pdfImportedPage = writer.getImportedPage(
pdfReader,currentPdfReaderPage);
pageContentByte.addTemplate(pdfImportedPage, 0, 0);
currentPdfReaderPage++;
}
currentPdfReaderPage = 1;
}
//Close document and outputStream.
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Pdf files merged successfully.");
}
public static void main(String args[]){
try {
//Prepare input pdf file list as list of input stream.
List<InputStream> inputPdfList = new ArrayList<InputStream>();
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_1.pdf"));
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_2.pdf"));
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_3.pdf"));
inputPdfList.add(new FileInputStream("..\\pdf\\pdf_4.pdf"));
//Prepare output stream for merged pdf file.
OutputStream outputStream =
new FileOutputStream("..\\pdf\\MergeFile_1234.pdf");
//call method to merge pdf files.
mergePdfFiles(inputPdfList, outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Multiple pdf merged method using org.apache.pdfbox:
public void mergePDFFiles(List<File> files,
String mergedFileName) {
try {
PDFMergerUtility pdfmerger = new PDFMergerUtility();
for (File file : files) {
PDDocument document = PDDocument.load(file);
pdfmerger.setDestinationFileName(mergedFileName);
pdfmerger.addSource(file);
pdfmerger.mergeDocuments(MemoryUsageSetting.setupTempFileOnly());
document.close();
}
} catch (IOException e) {
logger.error("Error to merge files. Error: " + e.getMessage());
}
}
From main program, call mergePDFFiles method using list of files and target file name.
String mergedFileName = "Merged.pdf";
mergePDFFiles(files, mergedFileName);
After calling mergePDFFiles, load merged file
File mergedFile = new File(mergedFileName);
package article14;
import java.io.File;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.util.PDFMergerUtility;
public class Pdf
{
public static void main(String args[])
{
new Pdf().createNew();
new Pdf().combine();
}
public void combine()
{
try
{
PDFMergerUtility mergePdf = new PDFMergerUtility();
String folder ="pdf";
File _folder = new File(folder);
File[] filesInFolder;
filesInFolder = _folder.listFiles();
for (File string : filesInFolder)
{
mergePdf.addSource(string);
}
mergePdf.setDestinationFileName("Combined.pdf");
mergePdf.mergeDocuments();
}
catch(Exception e)
{
}
}
public void createNew()
{
PDDocument document = null;
try
{
String filename="test.pdf";
document=new PDDocument();
PDPage blankPage = new PDPage();
document.addPage( blankPage );
document.save( filename );
}
catch(Exception e)
{
}
}
}
If you want to combine two files where one overlays the other (example: document A is a template and document B has the text you want to put on the template), this works:
after creating "doc", you want to write your template (templateFile) on top of that -
PDDocument watermarkDoc = PDDocument.load(getServletContext()
.getRealPath(templateFile));
Overlay overlay = new Overlay();
overlay.overlay(watermarkDoc, doc);
Using iText (existing PDF in bytes)
public static byte[] mergePDF(List<byte[]> pdfFilesAsByteArray) throws DocumentException, IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
Document document = null;
PdfCopy writer = null;
for (byte[] pdfByteArray : pdfFilesAsByteArray) {
try {
PdfReader reader = new PdfReader(pdfByteArray);
int numberOfPages = reader.getNumberOfPages();
if (document == null) {
document = new Document(reader.getPageSizeWithRotation(1));
writer = new PdfCopy(document, outStream); // new
document.open();
}
PdfImportedPage page;
for (int i = 0; i < numberOfPages;) {
++i;
page = writer.getImportedPage(reader, i);
writer.addPage(page);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
document.close();
outStream.close();
return outStream.toByteArray();
}
Some background to this question can be found at Check printing with Java/JSP and Create a "print-only" PDF with itext
I have been able to successfully create and open a PDF with a print dialog using iText-2.0.8 and the following code:
String outputFile = "firstdoc.pdf";
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputFile));
writer.setOpenAction(new PdfAction(PdfAction.PRINTDIALOG));
document.open();
document.add(new Paragraph("TEST"));
document.close();
I have also been able to use flying-saucer to generate a PDF from XHTML using the following code:
String inputFile = "firstdoc.xhtml";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
However, I can't seem to get the two to work together...
I would like to create the PDF using flying-saucer as in the 2nd code block and I would like to set the open action of that PDF to PdfAction.PRINTDIALOG.
How can I get these two sets of code to work together such that a flying-saucer created PDF opens with a print dialog initially?
You can implement org.xhtmlrenderer.pdf.PDFCreationListener of flying saucer and write your print dialog related code in preWrite(ITextRenderer iTextRenderer, int pageCount) method.
#Override
public void preWrite(ITextRenderer iTextRenderer, int pageCount)
{
iTextRenderer.getOutputDevice().getWriter().setOpenAction(new PdfAction(PdfAction.PRINTDIALOG));
}
Add this listener in ITextRenderer
ITextRenderer renderer = new ITextRenderer();
renderer.setListener(PDFCreationListener implemetation class);
renderer.setDocumentFromString(htmlContent);
renderer.layout();
renderer.createPDF(os);
Hope this helps.
Figured it out...
In case someone else needs this in the future, you can just use PdfStamper to modify a PDF that has already been created.
Here's the full code that worked for me:
import java.io.*;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfAction;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.FileOutputStream;
import java.io.IOException;
public class FirstDoc {
public static void main(String[] args) throws IOException, DocumentException {
String inputFile = "firstdoc.xhtml";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
PdfReader reader = new PdfReader(outputFile);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("firstdocprint.pdf"));
stamper.setPageAction(PdfWriter.PAGE_OPEN, new PdfAction(PdfAction.PRINTDIALOG), 1);
stamper.close();
}
}
Modification to flying saucer document.
PDDocument document = ...;
PDPage firstPage = document.getPage(0);
PDPageAdditionalActions actions = firstPage.getActions();
actions.setO(new PDActionJavaScript("this.print(true);\r")); // O for open