I'm currently using iText and I'm wondering if there is a way to delete a page from a PDF file?
I have opened it up with a reader etc., and I want to remove a page before it is then saved back to a new file; how can I do that?
The 'better' way to 'delete' pages is doing
reader.selectPages("1-5,10-12");
Which means we only select pages 1-5, 10-12 effectively 'deleting' pages 6-9.
Get the reader of existing pdf file by
PdfReader pdfReader = new PdfReader("source pdf file path");
Now update the reader by
pdfReader.selectPages("1-5,15-20");
then get the pdf stamper object to write the changes into a file by
PdfStamper pdfStamper = new PdfStamper(pdfReader,
new FileOutputStream("destination pdf file path"));
close the PdfStamper by
pdfStamper.close();
It will close the PdfReader too.
Cheers.....
For iText 7 I found this example:
PdfReader pdfReader = new PdfReader(PATH + name + ".pdf");
PdfDocument srcDoc = new PdfDocument(pdfReader);
PdfDocument resultDoc = new PdfDocument(new PdfWriter(PATH + name + "_cut.pdf"));
resultDoc.initializeOutlines();
srcDoc.copyPagesTo(1, 2, resultDoc);
resultDoc.close();
srcDoc.close();
See also here: clone-reordering-pages
and here: clone-splitting-pdf-file
You can use a PdfStamper in combination with PdfCopy.
In this answer it is explained how to copy a whole document. If you change the criteria for the loop in the sample code you can remove the pages you don't need.
Here is a removing function ready for real life usage. Proven to work ok with itext 2.1.7. It does not use "strigly typing" also.
/**
* Removes given pages from a document.
* #param reader document
* #param pagesToRemove pages to remove; 1-based
*/
public static void removePages(PdfReader reader, int... pagesToRemove) {
int pagesTotal = reader.getNumberOfPages();
List<Integer> allPages = new ArrayList<>(pagesTotal);
for (int i = 1; i <= pagesTotal; i++) {
allPages.add(i);
}
for (int page : pagesToRemove) {
allPages.remove(new Integer(page));
}
reader.selectPages(allPages);
}
Related
I need to copy whole AcroForm including field positions and values from template PDF to a new blank PDF file. How can I do that?
In short words - I need to get rid of "background" from the template and leave only filed forms.
The whole point of this is to create a PDF with content that would be printed on pre-printed templates.
I am using IText 5 but I can switch to 7 if usefull examples would be provided
After a lot of trial and error I have found the solution to "How to copy AcfroForm fields into another PDF". It is a iText v7 version. I hope it will help somebody someday.
private byte[] copyFormElements(byte[] sourceTemplate) throws IOException {
PdfReader completeReader = new PdfReader(new ByteArrayInputStream(sourceTemplate));
PdfDocument completeDoc = new PdfDocument(completeReader);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PdfWriter offsetWriter = new PdfWriter(out);
PdfDocument offsetDoc = new PdfDocument(offsetWriter);
offsetDoc.initializeOutlines();
PdfPage blank = offsetDoc.addNewPage();
PdfAcroForm originalForm = PdfAcroForm.getAcroForm(completeDoc, false);
// originalForm.getPdfObject().copyTo(offsetDoc,false);
PdfAcroForm offsetForm = PdfAcroForm.getAcroForm(offsetDoc, true);
for (String name : originalForm.getFormFields().keySet()) {
PdfFormField field = originalForm.getField(name);
PdfDictionary copied = field.getPdfObject().copyTo(offsetDoc, false);
PdfFormField copiedField = PdfFormField.makeFormField(copied, offsetDoc);
offsetForm.addField(copiedField, blank);
}
offsetDoc.close();
completeDoc.close();
return out.toByteArray();
}
Did you check the PdfCopyForms object:
Allows you to add one (or more) existing PDF document(s) to create a new PDF and add the form of another PDF document to this new PDF.
I didn't find an example, but you could try something like this:
PdfReader reader1 = new PdfReader(src1); // a document with a form
PdfReader reader2 = new PdfReader(src2); // a document without a form
PdfCopyForms copy = new PdfCopyForms(new FileOutputStream(dest));
copy.AddDocument(reader1); // add the document without the form
copy.CopyDocumentFields(reader2); // add the fields of the document with the form
copy.close();
reader1.close();
reader2.close();
I see that the class is deprecated. I'm not sure of that's because iText 7 makes it much easier to do this, or if it's because there were technical problems with the class.
Am using "itext-5.5.8", trying to insert (one) page of portrait pdf into a main pdf document, code works perfect but after inserting portrait pages automatically changes to landscape pages, don't know why?
CODE:
try {
PdfReader firstPdf = new PdfReader(mainFileWithPath); //main doc
PdfReader secondPdf =new PdfReader(addFileNameWithPath); // inserting pages
PdfStamper stamp = new PdfStamper(firstPdf, new FileOutputStream(outputPDFFile));
int totalNumOfPagesToInsert = secondPdf.getNumberOfPages();
int i =1;
while (i<=totalNumOfPagesToInsert) {
// Get a page(s) from secondPdf with the given pageNo
PdfImportedPage page = stamp.getImportedPage(secondPdf,i);
// insert new page in to the newly created pdf at specified page number.
stamp.insertPage(INSERT_AT_PAGE_NO + (i-1), secondPdf.getPageSize(i));
// copy the content of the page copied from secondPdf.
stamp.getUnderContent(INSERT_AT_PAGE_NO + (i-1)).addTemplate(page, 0, 0);
i++;
}
//close the new created pdf.
stamp.close();
Please give me directions to fix this! Thanks
As Author #Bruno Lowagie mentioned that "didn't take into account that rotation"
Have fixed the issue like ... Code Below ...
try {
PdfReader firstPdf = new PdfReader(mainFileWithPath);
PdfReader secondPdf =new PdfReader(addFileNameWithPath);
// create new pdf with the content from firstPdf
PdfStamper stamp = new PdfStamper(firstPdf, new FileOutputStream(outputPDFFile));
stamp.setRotateContents(false);
int totalNumOfPagesToInsert = secondPdf.getNumberOfPages();
int i =1;
while (i<=totalNumOfPagesToInsert) {
// Get a single page from secondPdf with the given pageNo
PdfImportedPage page = stamp.getImportedPage(secondPdf,i); //Actual working code
// insert new page in to the newly created pdf at specified page number.
// choose page size bas
stamp.insertPage(INSERT_AT_PAGE_NO + (i-1), secondPdf.getPageSizeWithRotation(i)); //Actual working code
// copy the content of the page copied from secondPdf.
stamp.getUnderContent(INSERT_AT_PAGE_NO + (i-1)).addTemplate(page, 0, 0); //Actual working code
i++;
}
//close the new created pdf.
stamp.close();
Here i am combining 2 pdf documents using the Itext packages.
Merging was done successfully using the code below
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();
for (InputStream in : list)
{
PdfReader reader = new PdfReader(in);
for (int i = 1; i <= reader.getNumberOfPages(); i++)
{
document.newPage();
//import the page from source pdf
PdfImportedPage page = writer.getImportedPage(reader, i);
//add the page to the destination pdf
cb.addTemplate(page, 0, 0);
}
}
outputStream.flush();
document.close();
outputStream.close();
Here the list is an InputStream List.
And outputStream is an output stream
The problem i am having is i want to append the PDFdocuments in the list after the 1st PDF is added
(i.e 1st PDF has 4 lines...i want the 2nd PDF to continue in the same page after the 4th line).
What i am getting is the 2nd PDF is added in the second page.
Is there any alternate keyword for document.newPage();
Can anyone help me with it.
Thanks would like to hear any responses:)
It depends on the requirements you have. As long as
you only are interested in the page contents of the merged PDFs, not in the page annotations and
the pages have no content but the text lines you mention, in particular no background graphics, watermarks, or header/footer lines,
you can you use either the
PdfDenseMergeTool from this answer or the
PdfVeryDenseMergeTool from this answer.
If you are interested in annotations, it should be no problem to extend those classes accordingly. If your PDDFs have background graphics or watermarks, headers or footers, they should be removed beforehand.
I have a business requirement that requires me to splits pdfs into multiple documents.
Lets say I have a 100MB pdf, I need to split that into for simplicity sake, into multiple pdfs no larger than 10MB a piece.
I am using iText.
I am going to get the original pdf, and loop through the pages, but how can I determine the file size of each page without writing it separately to the disk?
Sample code for simplicity
int numPages = reader.getNumberOfPages();
PdfImportedPage page;
for (int currentPage = 0; currentPage < numPages; ){
++currentPage;
//Get page from reader
page = writer.getImportedPage(reader, currentPage);
// I need the size in bytes here of the page
}
I think the easiest way is to write it to the disk and delete it afterwards:
Document document = new Document();
File f= new File("C:\\delete.pdf"); //for instance
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(f));
document.open();
document.add(page);
document.close();
long filesize = f.length(); //this is the filesize in byte
f.delete();
I'm not absolutely sure, I admit, but I don't know how it should be possible to figure out the filesize if the file is not existing.
I have to display a PDF document in a JSP page. The PDF document has 25 pages, but I want to display only 10 pages of the PDF file. How can I achieve this with help of iText?
Assuming you have the PDF file already.
You can use PdfStamper and PdfCopy to slice the PDF up:
PdfReader reader = new PdfReader("THE PDF SOURCE");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Document document = new Document();
PdfCopy copy = new PdfCopy(document, outputStream);
document.open();
PdfStamper stamper = new PdfStamper(reader, outputStream);
for (int i = 1; i < reader.getNumberOfPages(); i++) {
// Select what pages you need here
PdfImportedPage importedPage = stamper.getImportedPage(reader, i);
copy.addPage(importedPage);
}
copy.freeReader(reader);
outputStream.flush();
document.close();
// Now you can send the byte array to your user
// set content type to application/pdf
As for sending the pdf to display, it depends on the way you display it. The outputstream will at the end of the supplied code contain the pages you copy in the loop, in the example it is all of the pages.
This essentially is a new PDF file, but in memory. If it is the same 10 pages of the same file every time, you may consider saving it as a file.