I have a large single pdf document which consists of multiple records. Each record usually takes one page however some use 2 pages. A record starts with a defined text, always the same.
My goal is to split this pdf into separate pdfs and the split should happen always before the "header text" is found.
Note: I am looking for a tool or library using java or python. Must be free and available on Win 7.
Any ideas? AFAIK imagemagick won't work for this. May itext do this? I never used and it's
pretty complex so would need some hints.
EDIT:
Marked Answer led me to solution. For completeness here my exact implementation:
public void splitByRegex(String filePath, String regex,
String destinationDirectory, boolean removeBlankPages) throws IOException,
DocumentException {
logger.entry(filePath, regex, destinationDirectory);
destinationDirectory = destinationDirectory == null ? "" : destinationDirectory;
PdfReader reader = null;
Document document = null;
PdfCopy copy = null;
Pattern pattern = Pattern.compile(regex);
try {
reader = new PdfReader(filePath);
final String RESULT = destinationDirectory + "/record%d.pdf";
// loop over all the pages in the original PDF
int n = reader.getNumberOfPages();
for (int i = 1; i < n; i++) {
final String text = PdfTextExtractor.getTextFromPage(reader, i);
if (pattern.matcher(text).find()) {
if (document != null && document.isOpen()) {
logger.debug("Match found. Closing previous Document..");
document.close();
}
String fileName = String.format(RESULT, i);
logger.debug("Match found. Creating new Document " + fileName + "...");
document = new Document();
copy = new PdfCopy(document,
new FileOutputStream(fileName));
document.open();
logger.debug("Adding page to Document...");
copy.addPage(copy.getImportedPage(reader, i));
} else if (document != null && document.isOpen()) {
logger.debug("Found Open Document. Adding additonal page to Document...");
if (removeBlankPages && !isBlankPage(reader, i)){
copy.addPage(copy.getImportedPage(reader, i));
}
}
}
logger.exit();
} finally {
if (document != null && document.isOpen()) {
document.close();
}
if (reader != null) {
reader.close();
}
}
}
private boolean isBlankPage(PdfReader reader, int pageNumber)
throws IOException {
// see http://itext-general.2136553.n4.nabble.com/Detecting-blank-pages-td2144877.html
PdfDictionary pageDict = reader.getPageN(pageNumber);
// We need to examine the resource dictionary for /Font or
// /XObject keys. If either are present, they're almost
// certainly actually used on the page -> not blank.
PdfDictionary resDict = (PdfDictionary) pageDict.get(PdfName.RESOURCES);
if (resDict != null) {
return resDict.get(PdfName.FONT) == null
&& resDict.get(PdfName.XOBJECT) == null;
} else {
return true;
}
}
You can create a tool for your requirements using iText.
Whenever you are looking for code samples concerning (current versions of) the iText library, you should consult iText in Action — 2nd Edition the code samples from which are online and searchable by keyword from here.
In your case the relevant samples are Burst.java and ExtractPageContentSorted2.java.
Burst.java shows how to split one PDF in multiple smaller PDFs. The central code:
PdfReader reader = new PdfReader("allrecords.pdf");
final String RESULT = "record%d.pdf";
// We'll create as many new PDFs as there are pages
Document document;
PdfCopy copy;
// loop over all the pages in the original PDF
int n = reader.getNumberOfPages();
for (int i = 0; i < n; ) {
// step 1
document = new Document();
// step 2
copy = new PdfCopy(document,
new FileOutputStream(String.format(RESULT, ++i)));
// step 3
document.open();
// step 4
copy.addPage(copy.getImportedPage(reader, i));
// step 5
document.close();
}
reader.close();
This sample splits a PDF in single-page PDFs. In your case you need to split by different criteria. But that only means that in the loop you sometimes have to add more than one imported page (and thus decouple loop index and page numbers to import).
To recognize on which pages a new dataset starts, be inspired by ExtractPageContentSorted2.java. This sample shows how to parse the text content of a page to a string. The central code:
PdfReader reader = new PdfReader("allrecords.pdf");
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
System.out.println("\nPage " + i);
System.out.println(PdfTextExtractor.getTextFromPage(reader, i));
}
reader.close();
Simply search for the record start text: If the text from page contains it, a new record starts there.
Apache PDFBox has a PDFSplit utility that you can run from the command-line.
If you like Python, there's a nice library: PyPDF2. The library is pure python2, BSD-like license.
Sample code:
from PyPDF2 import PdfFileWriter, PdfFileReader
input1 = PdfFileReader(open("C:\\Users\\Jarek\\Documents\\x.pdf", "rb"))
# analyze pdf data
print input1.getDocumentInfo()
print input1.getNumPages()
text = input1.getPage(0).extractText()
print text.encode("windows-1250", errors='backslashreplacee')
# create output document
output = PdfFileWriter()
output.addPage(input1.getPage(0))
fout = open("c:\\temp\\1\\y.pdf", "wb")
output.write(fout)
fout.close()
For non coders PDF Content Split is probably the easiest way without reinventing the wheel and has an easy to use interface: http://www.traction-software.co.uk/pdfcontentsplitsa/index.html
hope that helps.
Related
How can I test whether a file that I'm opening in C# using FileStream is a "text type" file? I would like my program to open any file that is text based, for example, .txt, .html, etc.
But not open such things as .doc or .pdf or .exe, etc.
In general: there is no way to tell.
A text file stored in UTF-16 will likely look like binary if you open it with an 8-bit encoding. Equally someone could save a text file as a .doc (it is a document).
While you could open the file and look at some of the content all such heuristics will sometimes fail (eg. notepad tries to do this, by careful selection of a few characters notepad will guess wrong and display completely different content).
If you have a specific scenario, rather than being able to open and process anything, you should be able to do much better.
I guess you could just check through the first 1000 (arbitrary number) characters and see if there are unprintable characters, or if they are all ascii in a certain range. If the latter, assume that it is text?
Whatever you do is going to be a guess.
As others have pointed out there is no absolute way to be sure. However, to determine if a file is binary (which can be said to be easier than determining if it is text) some implementations check for consecutive NUL characters. Git apparently just checks the first 8000 chars for a NUL and if it finds one treats the file as binary. See here for more details.
Here is a similar C# solution I wrote that looks for a given number of required consecutive NUL. If IsBinary returns false then it is very likely your file is text based.
public bool IsBinary(string filePath, int requiredConsecutiveNul = 1)
{
const int charsToCheck = 8000;
const char nulChar = '\0';
int nulCount = 0;
using (var streamReader = new StreamReader(filePath))
{
for (var i = 0; i < charsToCheck; i++)
{
if (streamReader.EndOfStream)
return false;
if ((char) streamReader.Read() == nulChar)
{
nulCount++;
if (nulCount >= requiredConsecutiveNul)
return true;
}
else
{
nulCount = 0;
}
}
}
return false;
}
To get the real type of a file, you must check its header, which won't be changed even the extension is modified. You can get the header list here, and use something like this in your code:
using(var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
using(var reader = new BinaryReader(stream))
{
// read the first X bytes of the file
// In this example I want to check if the file is a BMP
// whose header is 424D in hex(2 bytes 6677)
string code = reader.ReadByte().ToString() + reader.ReadByte().ToString();
if (code.Equals("6677"))
{
//it's a BMP file
}
}
}
I have a below solution which works for me.This is general solution which check all types of Binary file.
/// <summary>
/// This method checks whether selected file is Binary file or not.
/// </summary>
public bool CheckForBinary()
{
Stream objStream = new FileStream("your file path", FileMode.Open, FileAccess.Read);
bool bFlag = true;
// Iterate through stream & check ASCII value of each byte.
for (int nPosition = 0; nPosition < objStream.Length; nPosition++)
{
int a = objStream.ReadByte();
if (!(a >= 0 && a <= 127))
{
break; // Binary File
}
else if (objStream.Position == (objStream.Length))
{
bFlag = false; // Text File
}
}
objStream.Dispose();
return bFlag;
}
public bool IsTextFile(string FilePath)
using (StreamReader reader = new StreamReader(FilePath))
{
int Character;
while ((Character = reader.Read()) != -1)
{
if ((Character > 0 && Character < 8) || (Character > 13 && Character < 26))
{
return false;
}
}
}
return true;
}
Below code works fine on iTextSharp 5.2.1
var file= new FileInfo(args[0]);
string name = file.Name.Substring(0,file.Name.LastIndexOf("."));
// we create a reader for a certain document
var reader = new PdfReader(args[0]);
// we retrieve the total number of pages
int numberOfPages = reader.NumberOfPages;
Console.WriteLine("There are " + n + " pages in the original file.");
Document document;
string filename;
PdfCopy copy;
for (int pageNumber = 1; i <= numberOfPages; i++)
{
filename = pageNumber.ToString();
filename = "_" + filename + ".pdf";
// step 1: creation of a document-object
document = new Document(reader.GetPageSizeWithRotation(pageNumber ));
// step 2: we create a writer that listens to the document
copy = new PdfCopy(document, new FileStream(name + filename,FileMode.Create));
// step 3: we open the document
document.Open();
copy.AddPage(copy.GetImportedPage(reader, pageNumber));
// step 5: we close the document
document.Close();
}
But it throws below error on iTextSharp 5.5.0,
The page 1 was requested but the document has only 0 pages.
it seems like that the last line actually tampered the reader instance. Could someone help me figure it out? Now I walkaround this by recreating a PdfReader instance for each page, but that is slow for large PDF file.
I finally nailed it. It's a change of iText in recent version that caused this issue, specifically, the issue lies in the WriteAllPages of the PdfReaderInstance.cs file. In it, the line
file.Close();
is the culprit. The reason is that Document.Close method will call PdfCopy.Close method which will in turn call PdfReaderInstance.WriteAllPages method and then all hells break loose.
On the surface, it seems a good practice to close the file, but really, it's none of your business, damn you, PdfReaderInstance.
Hope this info helps others.
iTextSharp page numbers are one-based, not zero. These two lines are accounting for this correctly:
pagenumber = i + 1;
document = new Document(reader.GetPageSizeWithRotation(pagenumber));
However this line is still going back to the zero-based index of your loop:
copy.AddPage(copy.GetImportedPage(reader, i));
You could just change that to:
copy.AddPage(copy.GetImportedPage(reader, pagenumber));
Of you could just make your entire loop one-based and not think about having to add one every once in a while
for (int pagenumber = 1; pagenumber <= n; pagenumber++)
{
filename = pagenumber.ToString();
while (filename.Length< digits) filename = "0" + filename;
filename = "_" + filename + ".pdf";
// step 1: creation of a document-object
document = new Document(reader.GetPageSizeWithRotation(pagenumber));
// step 2: we create a writer that listens to the document
copy = new PdfCopy(document, new FileStream(name+filename,FileMode.Create));
// step 3: we open the document
document.Open();
copy.AddPage(copy.GetImportedPage(reader, pagenumber));
// step 5: we close the document
document.Close();
}
I am creating a PDF using the cfdocument tag at the moment. The PDF is not much more than a bunch of links to other PDFs.
So I create this PDF index and the links are all HREFs
Another PDF
if I set the localURL attribute to "no" my URLs have the whole web path in them:
Another PDF
if I set the localURL attribute to "yes" then I get:
Another PDF
So this index PDF is going to go onto a CD and all of the linked PDFs are going to sit right next to it so I need a relative link ... more like:
Another PDF
cfdocument does not seem to do this. I can modify the file name of the document and make it "File:///Another_PDF.pdf" but this does not work either because I don't know the driveletter of the CD drive ... or if the files are going to end up inside a directory on the CD.
Is there a way (possibly using iText or something) of opening up the PDF once it is created and converting the URL links to actual PDF GoTo tags?
I know this is kind of a stretch but I am at my wits end with this.
So I've managed to get into the Objects but I'm still struggling with.
Converting from:
5 0 obj<</C[0 0 1]/Border[0 0 0]/A<</URI(File:///75110_002.PDF)/S/URI>>/Subtype/Link/Rect[145 502 184 513]>>endobj
To this:
19 0 obj<</SGoToR/D[0/XYZ null null 0]/F(75110_002.PDF)>>endobj
20 0 obj<</Subtype/Link/Rect[145 502 184 513]/Border[0 0 0]/A 19 0 R>>endobj
Wow this is really kicking my ass! :)
So I've managed to get the document open, loop through the Link Annotations, capture the Rect co-ordinates and the linked to document name (saved into an array of Structures) and then successfully deleted the Annotation which was a URI Link.
So now I thought I could now loop over that array of structures and put the Annotations back into the document using the createLink method or the setAction method. But all the examples I've seen of these methods are attached to a Chunk (of text). But my document already has the Text in place so I don't need to remake the text links I just need to put the Links back in in the same spot.
So I figured I could reopen the document and look for the actual text that was the link and then attache the setAction to th ealready existing chunk of text .... I can't find the text!!
I suck! :)
This thread has an example of updating the link actions, by modifying the pdf annotations. It is written in iTextSharp 5.x, but the java code is not much different.
The thread provides a solid explanation of how annotations work. But to summarize, you need to read in your source pdf and loop through the individual pages for annotations. Extract the links and use something like getFileFromPath() to replace them with a file name only.
I was curious, so I did a quick and ugly conversion of the iTextSharp code above. Disclaimer, it is not highly tested:
/**
Usage:
util = createObject("component", "path.to.ThisComponent");
util.fixLinks( "c:/path/to/sourceFile.pdf", "c:/path/to/newFile.pdf");
*/
component {
/**
Convert all absolute links, in the given pdf, to relative links (file name only)
#source - absolute path to the source pdf file
#destination - absolute path to save copy
*/
public function fixLinks( string source, string destination) {
// initialize objects
Local.reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( arguments.source );
Local.pdfName = createObject("java", "com.lowagie.text.pdf.PdfName");
// check each page for hyperlinks
for ( Local.i = 1; Local.i <= Local.reader.getNumberOfPages(); Local.i++) {
//Get all of the annotations for the current page
Local.page = Local.reader.getPageN( Local.i );
Local.annotations = Local.page.getAsArray( Local.PdfName.ANNOTS ).getArrayList();
// search annotations for links
for (Local.x = 1; !isNull( Local.annotations) && Local.x < arrayLen(Local.annotations); Local.x++) {
// get current properties
Local.current = Local.annotations[ Local.x ];
Local.dictionary = Local.reader.getPdfObject( Local.current );
Local.subType = Local.dictionary.get( Local.PdfName.SUBTYPE );
Local.action = Local.dictionary.get( Local.PdfName.A );
Local.hasLink = true;
//Skip this item if it does not have a link AND action
if (Local.subType != Local.PdfName.LINK || isNull(Local.action)) {
Local.hasLink = false;
}
//Skip this item if it does not have a URI
if ( Local.hasLink && Local.action.get( Local.PdfName.S ) != Local.PdfName.URI ) {
Local.hasLink = false;
}
//If it is a valid URI, update link
if (Local.hasLink) {
// extract file name from URL
Local.oldLink = Local.action.get( Local.pdfName.URI );
Local.newLink = getFileFromPath( Local.oldLink );
// replace link
// WriteDump("Changed link from ["& Local.oldLink &"] ==> ["& Local.newLink &"]");
Local.pdfString = createObject("java", "com.lowagie.text.pdf.PdfString");
Local.action.put( Local.pdfName.URI, Local.pdfString.init( Local.newLink ) );
}
}
}
// save all pages to new file
copyPDF( Local.reader , arguments.destination );
}
/**
Copy all pages in pdfReader to the given destination file
#pdfReader - pdf to copy
#destination - absolute path to save copy
*/
public function copyPDF( any pdfReader, string destination) {
try {
Local.doc = createObject("java", "com.lowagie.text.Document").init();
Local.out = createObject("java", "java.io.FileOutputStream").init( arguments.destination );
Local.writer = createObject("java", "com.lowagie.text.pdf.PdfCopy").init(Local.doc, Local.out);
// open document and save individual pages
Local.doc.open();
for (Local.i = 1; i <= arguments.pdfReader.getNumberOfPages(); Local.i++) {
Local.writer.addPage( Local.writer.getImportedPage( arguments.pdfReader, Local.i) );
}
Local.doc.close();
}
finally
{
// cleanup
if (structKeyExists(Local, "doc")) { Local.doc.close(); }
if (structKeyExists(Local, "writer")) { Local.writer.close(); }
if (structKeyExists(Local, "out")) { Local.out.close(); }
}
}
}
I finally got it:
public function resetLinks( string source, string destination) {
try {
// initialize objects
Local.reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( arguments.source );
Local.pdfName = createObject("java", "com.lowagie.text.pdf.PdfName");
Local.annot = createObject("java", "com.lowagie.text.pdf.PdfAnnotation");
Local.out = createObject("java", "java.io.FileOutputStream").init( arguments.destination );
Local.stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init(Local.reader, Local.out);
Local.PdfAction = createObject("java", "com.lowagie.text.pdf.PdfAction");
Local.PdfRect = createObject("java", "com.lowagie.text.Rectangle");
Local.PdfBorderArray = createObject("java", "com.lowagie.text.pdf.PdfBorderArray").init(javacast("float", "0"), javacast("float", "0"), javacast("float", "0"));
Local.newAnnots = [];
// check each page for hyperlinks
// Save the data to a structure then write it to an array
// then delete the hyperlink Annotation
for ( Local.i = 1; Local.i <= Local.reader.getNumberOfPages(); Local.i = Local.i + 1) {
//Get all of the annotations for the current page
Local.page = Local.reader.getPageN( Local.i );
Local.annotations = Local.page.getAsArray( Local.PdfName.ANNOTS ).getArrayList();
// search annotations for links
for (Local.x = arrayLen(Local.annotations); !isNull( Local.annotations) && Local.x > 0; Local.x--) {
// get current properties
Local.current = Local.annotations[ Local.x ];
Local.dictionary = Local.reader.getPdfObject( Local.current );
Local.subType = Local.dictionary.get( Local.PdfName.SUBTYPE );
Local.action = Local.dictionary.get( Local.PdfName.A );
Local.hasLink = true;
//Skip this item if it does not have a link AND action
if (Local.subType != Local.PdfName.LINK || isNull(Local.action)) {
Local.hasLink = false;
}
//Skip this item if it does not have a URI
if ( Local.hasLink && Local.action.get( Local.PdfName.S ) != Local.PdfName.URI ) {
Local.hasLink = false;
}
//If it is a valid URI, update link
if (Local.hasLink) {
// extract file name from URL
Local.oldLink = Local.action.get( Local.pdfName.URI );
Local.newLink = getFileFromPath( Local.oldLink );
Local.Rect = Local.dictionary.Get(PdfName.Rect);
arrayStruct = StructNew();
arrayStruct.rectSTR = Local.Rect.toString();
arrayStruct.link = Local.newLink;
arrayStruct.page = Local.i;
ArrayAppend(Local.newAnnots, arrayStruct);
// Delete
Local.annotations.remove(Local.current);
}
}
}
// Now really remove them!
Local.reader.RemoveUnusedObjects();
// Now loop over the saved annotations and put them back!!
for ( Local.z = 1; Local.z <= ArrayLen(Local.newAnnots); Local.z++) {
// Parse the rect we got save into an Array
theRectArray = ListToArray(ReplaceNoCase(ReplaceNoCase(Local.newAnnots[z].rectSTR, "[", ""), "]", ""));
// Create the GoToR action
theAction = Local.PdfAction.gotoRemotePage(javacast("string", '#Local.newAnnots[z].link#'), javacast("string", '#Local.newAnnots[z].link#'), javacast("boolean", "false"), javacast("boolean", "false"));
// Create the Link Annotation with the above Action and the Rect
theAnnot = Local.annot.createLink(Local.stamper.getWriter(), Local.PdfRect.init(javacast("int", theRectArray[1]), javacast("int", theRectArray[2]), javacast("int", theRectArray[3]), javacast("int", theRectArray[4])), Local.annot.HIGHLIGHT_INVERT, theAction);
// Remove the border the underlying underlined text will flag item as a link
theAnnot.setBorder(Local.PdfBorderArray);
// Add the Annotation to the Page
Local.stamper.addAnnotation(theAnnot, Local.newAnnots[z].page);
}
}
finally {
// cleanup
if (structKeyExists(Local, "reader")) { Local.reader.close(); }
if (structKeyExists(Local, "stamper")) { Local.stamper.close(); }
if (structKeyExists(Local, "out")) { Local.out.close(); }
}
}
I couldn't have done this without the help of Leigh!!
In a project I have to split a PDF document into two documents, one containing all blank pages, and one containing all pages with content.
For this job, I use a PdfReader to read the source file, and two pdfCopy objects (one for the blank pages document, one for the pages with content document) to write the files to.
I use GetImportedPage to read a PdfImportedPage, which is then added to one of the PdfCopy writers.
Now, the problem is the following: the source file is using the "tagged PDF format". To preserve this (which is absolutely required), I use the SetTagged() method on both PdfCopy writers, and use the extra third parameter in GetImportedPage(...) to keep the tagged format. However, when calling the AddPage(...) on the PdfCopy writer, I get an invalid cast exception:
"Unable to cast object of type 'iTextSharp.text.pdf.PdfDictionary' to type 'iTextSharp.text.pdf.PRIndirectReference'."
Anyone has any ideas on how to solve this ? Any hints ?
Also: the project currently refers version 5.1.0.0 of the itext libraries. In 5.4.4.0 the third parameter to GetImportedPage does not seem to be there anymore.
Below, you can find a code extract:
iTextSharp.text.Document targetPdf = new iTextSharp.text.Document();
iTextSharp.text.Document blankPdf = new iTextSharp.text.Document();
iTextSharp.text.pdf.PdfReader sourcePdfReader = new iTextSharp.text.pdf.PdfReader(inputFile);
iTextSharp.text.pdf.PdfCopy targetPdfWriter = new iTextSharp.text.pdf.PdfSmartCopy(targetPdf, new FileStream(outputFile, FileMode.Create));
iTextSharp.text.pdf.PdfCopy blankPdfWriter = new iTextSharp.text.pdf.PdfSmartCopy(blankPdf, new FileStream(blanksFile, FileMode.Append));
targetPdfWriter.SetTagged();
blankPdfWriter.SetTagged();
try
{
iTextSharp.text.pdf.PdfImportedPage page = null;
int n = sourcePdfReader.NumberOfPages;
targetPdf.Open();
blankPdf.Open();
blankPdf.Add(new iTextSharp.text.Phrase("This document contains the blank pages removed from " + inputFile));
blankPdf.NewPage();
for (int i = 1; i <= n; i++)
{
byte[] pageBytes = sourcePdfReader.GetPageContent(i);
string pageText = "";
iTextSharp.text.pdf.PRTokeniser token = new iTextSharp.text.pdf.PRTokeniser(new iTextSharp.text.pdf.RandomAccessFileOrArray(pageBytes));
while (token.NextToken())
{
if (token.TokenType == iTextSharp.text.pdf.PRTokeniser.TokType.STRING)
{
pageText += token.StringValue;
}
}
if (pageText.Length >= 15)
{
page = targetPdfWriter.GetImportedPage(sourcePdfReader, i, true);
targetPdfWriter.AddPage(page);
}
else
{
page = blankPdfWriter.GetImportedPage(sourcePdfReader, i, true);
blankPdfWriter.AddPage(page);
blankPageCount++;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception at LOC1: " + ex.Message);
}
The error occurs in the call to targetPdfWriter.AddPage(page); near the end of the code sample.
Thank you very much for your help.
Koen.
Dear Team,
In my application, i want to split the pdf using itextsharp. If i upload PDF contains 10 pages with file size 10 mb for split, After splitting the combine file size of each pdfs will result into above 20mb file size. If this possible to reduce the file size(each pdf).
Please help me to solve the issue.
Thanks in advance
This may have to do with the resources in the file. If the original document uses an embedded font on each, for example, then there will only be one instance of the font in the original file. When you split it, each file will be required have that font as well. The total overhead will be n pages × sizeof(each font). Elements that will cause this kind of bloat include fonts, images, color profiles, document templates (aka forms), XMP, etc.
And while it doesn't help you in your immediate problem, if you use the PDF tools in Atalasoft dotImage, your task becomes a 1 liner:
PdfDocument.Separate(userpassword, ownerpassword, origPath, destFolder, "Separated Page{0}.pdf", true);
which will take the PDF in orig file and create new pages in the dest folder each named with the pattern. The bool at the end is to overwrite an existing file.
Disclaimer: I work for Atalasoft and wrote the PDF library (also used to work at Adobe on Acrobat versions 1, 2, 3, and 4).
Hi Guys i modified the above code to split a PDF file into multiple Pdf file.
iTextSharp.text.pdf.PdfReader reader = null;
int currentPage = 1;
int pageCount = 0;
//string filepath_New = filepath + "\\PDFDestination\\";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
//byte[] arrayofPassword = encoding.GetBytes(ExistingFilePassword);
reader = new iTextSharp.text.pdf.PdfReader(filepath);
reader.RemoveUnusedObjects();
pageCount = reader.NumberOfPages;
string ext = System.IO.Path.GetExtension(filepath);
for (int i = 1; i <= pageCount; i++)
{
iTextSharp.text.pdf.PdfReader reader1 = new iTextSharp.text.pdf.PdfReader(filepath);
string outfile = filepath.Replace((System.IO.Path.GetFileName(filepath)), (System.IO.Path.GetFileName(filepath).Replace(".pdf", "") + "_" + i.ToString()) + ext);
reader1.RemoveUnusedObjects();
iTextSharp.text.Document doc = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(currentPage));
iTextSharp.text.pdf.PdfCopy pdfCpy = new iTextSharp.text.pdf.PdfCopy(doc, new System.IO.FileStream(outfile, System.IO.FileMode.Create));
doc.Open();
for (int j = 1; j <= 1; j++)
{
iTextSharp.text.pdf.PdfImportedPage page = pdfCpy.GetImportedPage(reader1, currentPage);
pdfCpy.SetFullCompression();
pdfCpy.AddPage(page);
currentPage += 1;
}
doc.Close();
pdfCpy.Close();
reader1.Close();
reader.Close();
}
Have you tried setting the compression on the writer?
Document doc = new Document();
using (MemoryStream ms = new MemoryStream())
{
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
writer.SetFullCompression();
}