I'm using ITextSharp to split multi-page PDF files into single page files. I also managed to add those single page PDFs to a zip file using MemoryStream.
Now, I need to add password protection to those PDFs using PdfStamper, before adding them into a zip file. But whenever I tried this, an ObjectDisposedException - Cannot access a closed Stream.
is being throwed.
Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile();
int cnt = 0;
try
{
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(new iTextSharp.text.pdf.RandomAccessFileOrArray(sourcePdfPath), new ASCIIEncoding().GetBytes(""));
for (cnt = 1; cnt <= reader.NumberOfPages; cnt++)
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (iTextSharp.text.Document document = new iTextSharp.text.Document())
{
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, memoryStream);
using (PdfStamper stamper = new PdfStamper(reader, memoryStream))
{
stamper.SetEncryption(
null,
Encoding.ASCII.GetBytes("password_here"),
PdfWriter.ALLOW_PRINTING,
PdfWriter.ENCRYPTION_AES_128);
}
memoryStreamForZipFile = new MemoryStream(memoryStream.ToArray());
memoryStreamForZipFile.Seek(0, SeekOrigin.Begin);
}
}
}
zipFile.Save(destinationFolder + "/" + fileName.Replace(".pdf", ".zip"));
reader.Close();
reader.Dispose();
}
catch
{
}
finally
{
GC.Collect();
}
return cnt - 1;
I have removed some codes above for clarity.
If I'll remove the PdfStamper "using" block, the code works just fine. I also tried to juggle the position of PdfStamper to see if I used it in the wrong place.
Am I not using using
blocks properly? Or I have to fix some code sequence in here?
You removed some lines that are essential are wrong; for instance: I assume that you are adding a PdfImportedPage
to the PdfContentByte
of a PdfWriter
. If that's so, you are ignoring all the warnings given in the official documentation.
You should replace your code by something like this:
PdfReader reader = new PdfReader(pathToFile);
int n = reader.NumberOfPages;
int cnt;
for (cnt = 1; cnt <= reader.NumberOfPages; cnt++)
{
reader = new PdfReader(pathToFile);
reader.SelectPages(cnt.ToString());
MemoryStream memoryStream = new MemoryStream();
using (PdfStamper stamper = new PdfStamper(reader, memoryStream))
{
stamper.SetEncryption(
null,
Encoding.ASCII.GetBytes("password_here"),
PdfWriter.ALLOW_PRINTING,
PdfWriter.ENCRYPTION_AES_128);
}
reader.Close();
// now do something with the memoryStream.ToArray()
}
As you can see, there is no need to introduce a Document
or a PdfWriter
object. If you use those classes, you throw away all interactivity that exists in the original pages. You also get into trouble if the page size of the original pages is different from A4.
Note that you can't reuse the PdfReader
instance when using PdfStamper
. Once you pass a PdfReader
instance to a PdfStamper
, that instance is tampered.