iText 7 and C# writing a PDF file from MemoryStream? - c#

I have a PDF document (using iText 7/C# 4.01) that I am creating in a MemoryStream and at the end, I want to write it out to a file. Part of the reason I am creating it in a memory stream is that I want to stamp a header table and footers on it at the end and was hoping to avoid writing it to a file then reading the file back in, stamping, then writing out a new file (as the examples I keep finding on iText website seem to do). However, I seem to be having some sort of chicken/egg scenario in the below code. It seems that you have to Close() the document in order for iText to fully form it. However, if I Close() it, then I get an ObjectDisposedException when trying to write it (simplified example below). I have to be missing something simple here, right? Thanks
MemoryStream baos = new MemoryStream();
PdfWriter writer = new PdfWriter(baos);
PdfDocument pdfDocument = new PdfDocument(writer.SetSmartMode(true));
//writer.SetCloseStream(true);
//pdfDocument.SetCloseWriter(true);
//pdfDocument.SetCloseReader(true);
//pdfDocument.SetFlushUnusedObjects(true);
Document d = new Document(pdfDocument, iText.Kernel.Geom.PageSize.LETTER);
d.Add(new Paragraph("Hello world!"));
//d.Close();
FileStream file = new FileStream("C:\test.pdf",
FileMode.Create, FileAccess.Write);
baos. WriteTo(file);
file.Close();
//baos.Close();
//d.Close();

Try this
I dont have IDE for test, but i think this work
MemoryStream baos = new MemoryStream();
PdfWriter writer = new PdfWriter(baos);
PdfDocument pdfDocument = new PdfDocument(writer.SetSmartMode(true));
Document d = new Document(pdfDocument, iText.Kernel.Geom.PageSize.LETTER);
d.Add(new Paragraph("Hello world!"));
d.Close();
byte[] byte1 = baos.ToArray();
File(byte1, "application/pdf", "C:\\iTextTester\\test.pdf");

Related

How to store Generated pdf on deployed website with Itext

I am trying to write to a pdf and send it in an email.I am able to implement this on my local machine. The problem is when I deploy to azure I am not sure where to store the pdf . I have seen one question regarding this
and tried this solution from stackoverflow -
Does iText (any version) work on Windows Azure websites?.
var path = Server.MapPath("test.pdf");
FileInfo dest = new FileInfo(path);
var writer = new PdfWriter(dest);
var pdf = new PdfDocument(writer);
var document = new Document(pdf);
document.Add(new Paragraph("hello world"));
document.Close();
I get an error
Could not find a part of the path
'D:\home\site\wwwroot\Email\test.pdf'.
Try to create the Pdf in memory and stream the content to the asp.net output stream.
Document document = new Document(PageSize.A4);
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
document.Open();
document.NewPage();
...
...
document.Close();
Response.Clear();
Response.ContentType = "application/pdf";
byte[] pdfBytes = ms.ToArray();
Response.AppendHeader("Content-Length", pdfBytes.Length.ToString());
Response.OutputStream.Write(pdfBytes, 0, (int)pdfBytes.Length);
I suppose your issue is related with the file path.
If I use the path like Server.MapPath("Azure_Example1.pdf"), I also get the same error as you.
I suggest you could try to use the relative path like Server.MapPath("~/Azure_Example1.pdf"). The '~/' points to the project root directory.
You could also set a break point to check the value of path by using remote debugging.
I have created a simple demo, it works fine on my side. You could refer to.
Install the iTextSharp 5.5.13 nuget package in Manage Nuget Packages.
Use the following code:
var path = Server.MapPath("~/Azure_Example1.pdf");
FileInfo dest = new FileInfo(path);
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
Document doc = new Document();
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
doc.Add(new Paragraph("Hello World")); //change content in pdf
doc.Close();
Finally, you could see the pdf file has been stored in root project directory.

How to create a PDF containing text?

I want to create a PDF document containing some text that I have in the form of a string. This is what I have so far:
iTextSharp.text.Document d = new iTextSharp.text.Document();
string dosya = (#"C:\Deneme.pdf");
PdfWriter.GetInstance(d, new System.IO.FileStream(dosya, System.IO.FileMode.Create));
d.AddSubject(text);
Your question is unclear because you don't mention if you want to create a PDF from scratch (which may be what you want to do based on your code sample) or if you want to add text to an existing PDF (which is what the subject of your question suggests).
In both cases, you should take a look at the official documentation.
If you want to create a PDF from scratch, take a look at the Hello World example:
public void CreatePdf(Stream stream) {
// step 1
using (Document document = new Document()) {
// step 2
PdfWriter.GetInstance(document, stream);
// step 3
document.Open();
// step 4
document.Add(new Paragraph("Hello World!"));
}
}
The value of stream can be any output stream (one that writes to memory, one that writes to a file,...).
If you want to add a string to an existing PDF, take a look at a PdfStamper example.
public static byte[] Stamp(byte[] resource) {
PdfReader reader = new PdfReader(resource);
using (var ms = new MemoryStream()) {
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
PdfContentByte canvas = stamper.GetOverContent(1);
ColumnText.ShowTextAligned(
canvas,
Element.ALIGN_LEFT,
new Phrase("Hello people!"),
36, 540, 0
);
}
return ms.ToArray();
}
}
These examples were taken from a book I once wrote. You will find the examples through this link: http://developers.itextpdf.com/examples/itext-action-second-edition
This answer assumes that you are using iText 5 (an assumption that is based on your code snippet). The most recent version is iText 7. That requires code that is totally different.

Writing Multiple Pages to a Xps Document

I am having trouble writing multiple pages to an xps document. I have a loop that goes through my opened windows and saves the last window. this presents to a pdf fine, however it is just the last window in wpf.
MemoryStream lMemoryStream = new MemoryStream();
Package package = Package.Open(lMemoryStream, FileMode.Create);
XpsDocument doc = new XpsDocument(package);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
writer.Write(Report.reportWindow);
doc.Close();
package.Close();
var pdfXpsDoc = PdfSharp.Xps.XpsModel.XpsDocument.Open(lMemoryStream);
PdfSharp.Xps.XpsConverter.Convert(pdfXpsDoc, filename, 0);
I have tried changing the FileMode to Append. However, this comes up with an error "Append and Truncate not supported".

Filling out XFA PDF using iTextSharp, data not saving (C#)

I have an XFA PDF file (which I did not author). It's a third-party form which I'm trying to fill out. I filled out the form manually, then I used iTextSharp save the full XML DomDocument from it. Now I'm trying to apply that same XML file programmatically. However, the resulting PDF doesn't have any of the fields filled in. This is the code I'm using to apply the XML file:
PdfReader pdfReader = new PdfReader(inputPdf);
using (MemoryStream ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(pdfReader, ms, '\0', true))
{
XfaForm xfaForm = new XfaForm(pdfReader);
XmlDocument doc = new XmlDocument();
doc.Load(inputXml);
xfaForm.DomDocument = doc;
xfaForm.Changed = true;
XfaForm.SetXfa(xfaForm, stamper.Reader, stamper.Writer);
}
var bytes = ms.ToArray();
System.IO.File.WriteAllBytes(outputPdf, bytes);
}
inputPdf is the path to the original empty PDF file.
inputXml is the path to the XML file extracted from the filled out PDF file. This is the entire XML file, and not just the datasets section.
What's interesting is that if I create the PdfStamper object like this instead:
new PdfStamper(pdfReader, ms);
then I see the data in the fields, but of course then I have the associated issues with not appending.
Any suggestions on what I might be doing wrong? I just can't seem to get any of the changes to the DomDocument to save.

merge 2 pdf with itextsharp stamper

I want to take 2 pdf files and merge them together.
each file is one page long. the reason to merge them is that one file is simply a footer. The footer needs to be attached to the existing file.
I'm using a stamper to try and merge the 2 files.
I successfully create the output file, but it doesn't have the footer. It's just a copy of the original input file. Any idea why they aren't merging?
using (Stream inputPdfStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
using (Stream inputPdfFooterStream = new FileStream(footerPdf, FileMode.Open, FileAccess.Read, FileShare.Read))
using (Stream outputPdfStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
var reader = new PdfReader(inputPdfStream);
var stamper = new PdfStamper(reader, outputPdfStream);
var pdfContentByte = stamper.GetOverContent(1);
stamper.FormFlattening = true;
stamper.Close();
}
There are different problems with your question.
Problem #1: why did you add the line stamper.FormFlattening = true;? Are you working with a form? I don't see you do anything with forms, so why would you flatten the document?
Problem #2: You say you want to merge two documents with PdfStamper. That is misleading. Merging documents is done with PdfCopy. From your explanation, I gather that you want to superimpose two documents. You are right that you need PdfStamper to do so.
Problem #3: You want to use a specific document containing a footer as company stationery. In that case, you want to add the content of the stationery under the actual content. Then why are you using stamper.GetOverContent(1);? Use stamper.GetUnderContent(1); instead.
Problem #4: You are creating an inputPdfFooterStream to read the document with the footer, but I don't see you using that stream anywhere. What do you expect?
Problem #5: You didn't read the documentation. This is your main problem. Download chapter 6 of my book (it's available for free, and I've been referring to it in dozens of answers on StackOverflow). Go to page 176 where it says "Adding company stationery to an existing document". That example meets your requirement completely!
// Create readers
PdfReader reader = new PdfReader(src);
PdfReader s_reader = new PdfReader(stationery);
using (MemoryStream ms = new MemoryStream()) {
// Create the stamper
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
// Add the stationery to each page
PdfImportedPage page = stamper.GetImportedPage(s_reader, 1);
int n = reader.NumberOfPages;
PdfContentByte background;
for (int i = 1; i <= n; i++) {
background = stamper.GetUnderContent(i);
background.AddTemplate(page, 0, 0);
}
}
return ms.ToArray();
}
In your code, you only have one reader. In my code, I also have an object called s_reader that takes the footerPdf document and allows you to created a PdfImportedPage:
PdfImportedPage page = stamper.GetImportedPage(s_reader, 1);
This page is then added under the existing content of the actual document:
background = stamper.GetUnderContent(i);
background.AddTemplate(page, 0, 0);
Note that this example assumes that both documents have the same page size and that the origin of the coordinate system of the document with the actual content coincided with the lower-left corner. If that isn't the case with your PDFs, you can have a situation where the footer isn't visible or is only partly visible. Also: if the document with the actual content is opaque, it will also make the footer invisible.

Categories