I am using Visual Studio 2013, c# Windows Application, iTextSharp:
I can easily create/save a pdf file and write to it but is there a way to just use a pdf file and write to it without first saving it? I don't want to be creating a temporary pdf file every-time someone runs a report. Thanks in Advance !!
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10,10,42,35);
PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream("Test.pdf",
FileMode.Create));
doc.Open();
\\\\ Then I do a bunch of stuff, then do a close
doc.Close();
You can use a MemoryMappedFile and write to it and it is not disk based.
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("INMEMORYPDF.pdf", 1000000))
{
PDFPageMargins margins = new PDFPageMargins(10, 10, 10, 10);
var document = new Document((_pageWidth > 540) ? PageSize.A4.Rotate() : PageSize.A4, margins.Left, margins.Right, margins.Top, margins.Bottom);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
PdfWriter.GetInstance(document, stream);
document.Open();
//MODIFY DOCUMENT
document.Close();
}
byte[] content;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader rdr = new BinaryReader(stream);
content = new byte[mmf.CreateViewStream().Length];
rdr.Read(content, 0, (int)mmf.CreateViewStream().Length);
}
return content;
}
Related
I am trying to add a Cover Page PDF file to another PDF file. I am using CopyPagesTo method. CoverPageFilePath will go before any pages in the pdfDocumentFile. I then need to rewrite that new file to the same location. When I run the code and open the new pdf file I get an error about it being damaged.
public static void iText7MergePDF()
{
byte[] modifiedPdfInBytes = null;
string pdfCoverPageFilePath = #"PathtoCoverPage\Cover Page.pdf";
PdfDocument pdfDocumentCover = new PdfDocument(new iText.Kernel.Pdf.PdfReader(pdfCoverPageFilePath));
string pdfDocumentFile =#"PathtoFullDocument.pdf";
var buffer = File.ReadAllBytes(pdfDocumentFile);
using (var originalPdfStream = new MemoryStream(buffer))
using (var modifiedPdfStream = new MemoryStream())
{
var pdfReader = new iText.Kernel.Pdf.PdfReader(originalPdfStream);
var pdfDocument = new PdfDocument(pdfReader, new PdfWriter(modifiedPdfStream));
int numberOfPages = pdfDocumentCover.GetNumberOfPages();
pdfDocumentCover.CopyPagesTo(1, numberOfPages, pdfDocument);
modifiedPdfInBytes = modifiedPdfStream.ToArray();
pdfDocument.Close();
}
System.IO.File.WriteAllBytes(pdfGL, modifiedPdfInBytes);
}
Whenever you have some other type, like a StreamWriter, or here a PdfWriter writing to a Stream, it may not write all the data to the Stream immediately.
Here you Close the pdfDocument for all the data to be written to the MemoryStream.
ie this
modifiedPdfInBytes = modifiedPdfStream.ToArray();
pdfDocument.Close();
Should be
pdfDocument.Close();
modifiedPdfInBytes = modifiedPdfStream.ToArray();
I have a pdf document (created by iTextSharp - free version 4.1.6) and I want to add text / table at the top of this pdf. I have tried to create two memory streams from iTextSharp Documents and combine them to one, see my code below. But the new PDF file cannot be opened. Any ideas what I am doing wrong? Any other ideas to add text / table at the top of an existing PDF? Thanks in advance!
public void CreateTestPDF(string _pathOfOriginalPDF, string _pathOfModifiedPDF)
{
string oldFile = _pathOfOriginalPDF;
string newFile = pathOfModifiedPDF;
byte[] bytesHeader;
byte[] bytesBody;
byte[] bytesCombined;
using (MemoryStream ms = new MemoryStream())
{
Document doc = new Document();
doc.Open();
doc.Add(new Paragraph("This is my header paragraph"));
if (doc.IsOpen())
{
doc.Close();
}
bytesHeader = ms.ToArray();
}
using (MemoryStream ms = new MemoryStream())
{
Document doc = new Document();
//doc.Open();
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(oldFile, FileMode.Create));
if (doc.IsOpen())
{
doc.Close();
}
bytesBody = ms.ToArray();
}
IEnumerable<byte> iCombined = bytesHeader.Concat(bytesBody);
bytesCombined = iCombined.ToArray();
string testFile = _pathOfModifiedPDF;
using (FileStream fs = File.Create(testFile))
{
fs.Write(bytesBody, 0, (int)bytesBody.Length);
}
}
I have created a console app that uses a memory stream to create a pdf file, to encrypt it and the add it as an attachment.
using (Stream output = new MemoryStream())
{
Document document = new Document();
using (var stream = new MemoryStream())
{
PdfWriter.GetInstance(document, stream);
document.Open();
var image = Image.GetInstance(renderedPayslip);
image.ScaleToFit(600, 820);
image.SetAbsolutePosition(2, 10);
document.Add(image);
using (var newTestStream = new MemoryStream())
{
stream.CopyTo(newTestStream);
newTestStream.Position = 0;
document.Close();
PdfReader reader = new PdfReader(stream.ToArray());
PdfStamper stamper = new PdfStamper(reader, newTestStream);
PdfEncryptor.Encrypt(reader, newTestStream, true, "secret", "secret", PdfWriter.ALLOW_PRINTING);
reader.Close();
}
//return sm.ToArray();
}
The problem is that it keeps on giving the message PDF Header not found.
Can some one help, please?
I am trying to use iTextSharp to read/modify PDF metadata. Without showing any information to the user. I gone through below code:
iTextSharp.text.Document document = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 20f, 20f, 20f, 20f);
using (MemoryStream memStream = new MemoryStream())
{
using (PdfWriter wri = PdfWriter.GetInstance(document, memStream))
{
document.Open(); document.AddSubject("Test"); document.Close();
}
}
I would greatly appreciate any pointers to the solution.
The code snippet you are using is about adding metadata to a PDF document that is created from scratch. You are asking to read metadata from an existing PDF document. Please take a look at the documentation on the iText website, more specifically to Q&A entry How to add / delete / retrieve information from a PDF using a custom property?
Granted, the code used in the answer to that question is written in Java, but it's fairly easy to port it to C#. Here's another snippet:
public byte[] ManipulatePdf(byte[] src) {
PdfReader reader = new PdfReader(src);
using (MemoryStream ms = new MemoryStream()) {
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
Dictionary<String, String> info = reader.Info;
info["Title"] = "Hello World stamped";
info["Subject"] = "Hello World with changed metadata";
info["Keywords"] = "iText in Action, PdfStamper";
info["Creator"] = "Silly standalone example";
info["Author"] = "Also Bruno Lowagie";
stamper.MoreInfo = info;
}
return ms.ToArray();
}
}
You can retrieve the metadata from an existing PDF through PdfReader. You get a Dictionary where the keys correspond with the keys of the info dictionary in ISO-32000-1. If you want to change the metadata, you can do so with PdfStamper.
This functionality will read and adapt the Info dictionary (which is what you referred to in your code snippet). The PDF can also contains XMP metadata.
XMP metadata can be read like this:
public string ReadXmpMetadata(byte[] src) {
PdfReader reader = new PdfReader(src);
byte[] b = reader.Metadata;
return Encoding.UTF8.GetString(b, 0, b.Length);
}
You can change the XMP metadata like this:
public byte[] ManipulatePdf(byte[] src) {
PdfReader reader = new PdfReader(src);
using (MemoryStream ms = new MemoryStream()) {
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
Dictionary<String, String> info = reader.Info;
using (MemoryStream msXmp = new MemoryStream()) {
XmpWriter xmp = new XmpWriter(msXmp, info);
xmp.Close();
stamper.XmpMetadata = msXmp.ToArray();
}
}
return ms.ToArray();
}
}
I am assuming that you know the difference between the Info dictionary and an XMP metadata stream in PDF.
I create simple test PDF document using iTextSharp. I'm just using PdfContentByte to show some text. This is the code:
Document document = new Document();
Stream outStream = new FileStream("D:\\aaa\\test.pdf", FileMode.OpenOrCreate);
PdfWriter writer = PdfWriter.GetInstance(document, outStream);
document.Open();
PdfContentByte to = writer.DirectContent;
to.BeginText();
to.SetFontAndSize(BaseFont.CreateFont(), 12);
to.SetTextMatrix(0, 0);
to.ShowText("aaa");
to.EndText();
document.Close();
outStream.Close();
The file is created but when I try to open it(using Acrobat Reader), all I get is following message:
There was an error opening this
document. There was a problem reading
this document (14).
Where is the problem ? How do I fix it? Thank you
Problem was solved after restarting VS. No code change was made.
I can't seem to replicate the problem you're encountering, but please take into account potential leaks of resources due to any exceptional conditions you may encounter and properly Dispose() those objects as such:
using (Stream outStream = new FileStream("D:\\aaa\\test.pdf", FileMode.OpenOrCreate))
{
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, outStream);
document.Open();
try
{
PdfContentByte to = writer.DirectContent;
to.BeginText();
try
{
to.SetFontAndSize(BaseFont.CreateFont(), 12);
to.SetTextMatrix(0, 0);
to.ShowText("aaa");
}
finally
{
to.EndText();
}
}
finally
{
document.Close();
}
}