aspx to pdf using itextSharp 5.3.0 - asp.net

I am using this dll iTextSharp 5.3.0 to make a pdf file .
Is there a way to convert full .aspx page in pdf ? My page has grids and server side code .
This is my code:
protected void Button1_Click(object sender, EventArgs e)
{
createPDF(Server.MapPath("Default.aspx"));
}
private void createPDF(string html)
{
TextReader reader = new StringReader(html);
// step 1: creation of a document-object
Document document = new Document(PageSize.A4, 30, 30, 30, 30);
// step 2:
// we create a writer that listens to the document
// and directs a XML-stream to a file
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c://test.pdf", FileMode.Create));
HTMLWorker worker = new HTMLWorker(document);
document.Open();
worker.StartDocument();
List<IElement> p = HTMLWorker.ParseToList(new StreamReader(html), new StyleSheet());
for (int k = 0; k < p.Count; k++)
{
document.Add((IElement)p[k]);
}
worker.EndDocument();
worker.Close();
document.Close();
}
It's working but the file test.pdf is just plain text. The html isn't well interpreted, my grids are missing and my server side values (the values from the grids) are also missing .
I also tried the codes from here:
http://forums.asp.net/t/1199774.aspx
and here:
Problem with HTMLParser in Itextsharp
Thanks in advance!

This is my honest advice! Don't waste your time on the HTMLWorker.ParseToList. It has a very elementary HTML parser.
Try this packge and you will never look back!
https://github.com/pruiz/WkHtmlToXSharp

ITextSharp only renders inline css, it is giving problem while adding CSS files.
System.Web.HttpContext.Current.Response.ContentType = "application/pdf";
System.Web.HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=BookingDetails.pdf");
System.Web.HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
this.CreateBookingMainDiv.RenderControl(hw);
StringReader sr = new StringReader(sw.ToString());
Document pdfDoc = new Document(new Rectangle(922,1296),7f,7f,7f,0f);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, System.Web.HttpContext.Current.Response.OutputStream);
pdfDoc.Open();
//HtmlPipeline
CssAppliers ca = new CssAppliersImpl();
//ICssFile cfile = new CssFileProcessor();
HtmlPipelineContext htmlContext = new HtmlPipelineContext(ca);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
//CSS stuff
//var cssResolver = new StyleAttrCSSResolver();
//var DamcoCss = XMLWorkerHelper.GetCSS(new FileStream(HttpContext.Current.Server.MapPath("~/css/damco.css"), FileMode.Open));
ICssFile cfile = new CssFileImpl();
ICSSResolver cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true);
//String DamcoCss = HttpContext.Current.Server.MapPath("~/css/damco.css");
//String BootStrapCss = HttpContext.Current.Server.MapPath("~/css/bootstrap.css");
//String BootStrapCssTheme = HttpContext.Current.Server.MapPath("~/css/bootstrap-theme.css");
//Add the external CSS file
//cssResolver.AddCssFile(DamcoCss, true);
//cssResolver.AddCssFile(BootStrapCss, true);
//cssResolver.AddCssFile(BootStrapCssTheme, true);
//Pipeline
IPipeline pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(pdfDoc, writer)));
//XMLWorker
XMLWorker worker = new XMLWorker(pipeline, true);
//and...we parse
XMLParser parser = new XMLParser(true, worker);
//parser.AddListener(worker);
parser.Parse(sr);
parser.Flush();
pdfDoc.Close();
System.Web.HttpContext.Current.Response.Write(pdfDoc);
System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest();
//System.Web.HttpContext.Current.Response.End();
Use XMLWorker instead of HTMLWorker. works like charm.

Related

TextBox controls are not Working with Export To PDF(iTextSharp)

I have an HTML form, which contains lables and textboxes.
After filling this form, it is exported to PDF.
All the label Texts are exported. But the textbox text is not exported to PDF.
Code
protected void btnExportPDF_Click(object sender, EventArgs e)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=DecForm.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
this.divToPdf.RenderControl(hw);
StringReader sr = new StringReader(sw.ToString());
Document pdfDoc = new Document(PageSize.A4, 10, 10, 2, 10);
HTMLWorker htmlparser = new HTMLWorker(pdfDoc);
PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.Open();
htmlparser.Parse(sr);
pdfDoc.Close();
Response.Write(pdfDoc);
Response.End();
}
Why are the textbox text not exported through to PDF?
I think that when you're rendering divToPDF you are getting a fresh cut of the html and it does not have the values there were populated on the page. You may want to look at using the divToPDF is you'll want to look at accessing the InnerHtml or OuterHtml property and use that.
Try this.
List<IElement> elements = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(new StringReader(htmlString), null);
//htmlString is your form html
foreach (IElement el in elements)
{
pdfDoc.add(el);
}

Merging 2 gridviews into one generated PDF file using iTextSharp

I'm using 2 gridviews. The first one has paging enabled, and the number of rows allowed per page is one. The second gridview takes values from the first row as time range, and everytime I change the page on gridview1 the second GV changes it's content automatically based on GV1's values.
Previously, I was able to generate a PDF file using iTextSharp with only one gridview and no paging enabled. But now I'm struggling first of all with the paging enabled, and second with merging both gridviews into one pdf file.
Anybody know how can I do that?
Thanks in advance.
EDIT: This is the code I use to generate a PDF file from a gridview using iTextSharp.
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using iTextSharp.text.html.simpleparser;
StringWriter stw = new StringWriter();
HtmlTextWriter htextw = new HtmlTextWriter(stw);
gvReportes.AllowPaging = false;
gvReportes.HeaderRow.Style.Add("font-family", "Arial, Helvetica, sans-serif;");
gvReportes.HeaderRow.Style.Add("font-size", "7.20px");
gvReportes.HeaderRow.Style.Add("color", "#284775");
gvReportes.Style.Add("font-family", "Arial, Helvetica, sans-serif;");
gvReportes.Style.Add("font-size", "6px");
gvReportes.RenderControl(htextw);
Document document = new Document();
string path = "path.pdf";
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(path, FileMode.Create));
document.Open();
StringReader str = new StringReader(stw.ToString());
HTMLWorker htmlworker = new HTMLWorker(document);
htmlworker.Parse(str);
Response.Write(document);
document.Close();
And this is how the gridviews are displayed, as you can see the values "Salida" and "Llegada" on GV1 work as a time range to display data on GV2.
protected void Button1_Click(object sender, EventArgs e)
{
Response.Clear(); //this clears the Response of any headers or previous output
Response.Buffer = true; //ma
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=injoin.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
GridView1.RenderControl(hw);
StringReader sr = new StringReader(sw.ToString());
Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
HTMLWorker htmlparser = new HTMLWorker(pdfDoc);
PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.Open();
htmlparser.Parse(sr);
pdfDoc.Close();
Response.Write(pdfDoc);
Response.End();
}

Displaying a web page as a pdf with click of a button

I have a new requirement to have a button in my web page, and upon clicking, it displays the web page as a PDF. On researching I found that iTextSharp is used for such purpose.
But I have many Telerik and ASP controls in my web page too. Can I get that also in the PDF using iTextSharp?
If yes then can anyone please provide me a basic link to start using iTextSharp as I haven't came across this tool yet.
According to the answer from #ahaliav I tried with the following code. However, I'm not getting the controls on the pdf.
protected void btnExport_Click(object sender, EventArgs e)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
MemoryStream msOutput = new MemoryStream();
TextReader reader = new StringReader(HtmlContent);
// step 1: creation of a document-object
Document document = new Document(PageSize.A4, 30, 30, 30, 30);
HTMLWorker worker = new HTMLWorker(document);
// step 2:
// we create a writer that listens to the document
// and directs a XML-stream to a file
PdfWriter writer = PdfWriter.GetInstance(document, Response.OutputStream);
// step 3: we create a worker parse the document
// step 4: we open document and start the worker on the document
document.Open();
worker.StartDocument();
// step 5: parse the html into the document
worker.Parse(reader);
// step 6: close the document and the worker
worker.EndDocument();
worker.Close();
document.Close();
//Response.Write(document);
//Response.End();
}
protected override void Render(HtmlTextWriter writer)
{
// setup a TextWriter to capture the markup
TextWriter tw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(tw);
// render the markup into our surrogate TextWriter
base.Render(htw);
// get the captured markup as a string
string pageSource = tw.ToString();
// render the markup into the output stream verbatim
writer.Write(pageSource);
// remove the viewstate field from the captured markup
HtmlContent = Regex.Replace(pageSource,
"<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\".*?\" />",
"", RegexOptions.IgnoreCase);
// the page source, without the viewstate field, is in viewStateRemoved
// do what you like with it
}
Please help .
I have other option also,that is to display the image of the full web page when i click a button.Can anyone guide me to any possible directions for these two issues please.
I finally changed my code as:
Response.ContentType = "application/msword";
Response.AddHeader("content-disposition", "attachment;filename=TestPage.doc");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
MemoryStream msOutput = new MemoryStream();
With this i am able to get the msword document containing all my controls ,but i am also getting some unwanted texts,how can i remove that,if anyone encountered the same problem?
After some research i did not find any solution for showing the controls in the html this code below works fine but with out showing the controls,
in the past i used this http://www.winnovative-software.com/ and it works good for html pages including all controlls you can also test it onlie, the "only" problem is it you need to pay for the license
protected void btnExportToPdf_Click(object sender, EventArgs e)
{
renderPDF = true;
}
protected override void Render(HtmlTextWriter writer)
{
if (renderPDF == true)
{
MemoryStream mem = new MemoryStream();
StreamWriter twr = new StreamWriter(mem);
HtmlTextWriter myWriter = new HtmlTextWriter(twr);
base.Render(myWriter);
myWriter.Flush();
myWriter.Dispose();
StreamReader strmRdr = new StreamReader(mem);
strmRdr.BaseStream.Position = 0;
string pageContent = strmRdr.ReadToEnd();
strmRdr.Dispose();
mem.Dispose();
writer.Write(pageContent);
CreatePDFDocument(pageContent);
}
else
{
StringBuilder sb = new StringBuilder();
HtmlTextWriter tw = new HtmlTextWriter(new System.IO.StringWriter(sb));
base.Render(tw);
// get the captured markup as a string
string pageSource = tw.ToString();
//Get the rendered content
string sContent = sb.ToString();
//Now output it to the page, if you want
writer.Write(sContent);
}
}
public void CreatePDFDocument(string strHtml)
{
string strHTMLpath = Server.MapPath("MyHTML.html");
StreamWriter strWriter = new StreamWriter(strHTMLpath, false, Encoding.UTF8);
strWriter.Write(strHtml);
strWriter.Close();
string strFileName = HttpContext.Current.Server.MapPath("map1.pdf"); // strFileName "C:\\Inetpub\\wwwroot\\Test\\map1.pdf"
// step 1: creation of a document-object
Document document = new Document();
// step 2:
// we create a writer that listens to the document
PdfWriter.GetInstance(document, new FileStream(strFileName, FileMode.Create));
StringReader se = new StringReader(strHtml);
TextReader tr = new StreamReader(Server.MapPath("MyHTML.html"));
//add the collection to the document
document.Open();
/////////
iTextSharp.text.html.simpleparser.HTMLWorker worker = new iTextSharp.text.html.simpleparser.HTMLWorker(document);
worker.StartDocument();
//// step 5: parse the html into the document
worker.Parse(tr);
//// step 6: close the document and the worker
worker.EndDocument();
//worker.Parse(tr); // getting error "Illegal characters in path"
document.Close();
ShowPdf(strFileName);
}
public void ShowPdf(string strFileName)
{
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "inline;filename=" + strFileName);
Response.ContentType = "application/pdf";
Response.WriteFile(strFileName);
Response.Flush();
Response.Clear();
}
A very simple Google search brings us to the following forum thread which has your "sollution":
http://forums.asp.net/t/1039486.aspx/1
iTextSharp comes with a little companion : XML Worker
For a demo, have a look here
Even though the documentation refers to the Java API, the adaptation to C# should be straightforward.
As for Telerik/ASP tags, you can extend XMLWorker and define how to convert such tags into PDF elements.

Open Generated pdf file through code directly without saving it onto the disk

I use Sharepoint 2010 and I am developing a web part where on a button click event, a pdf file needs to be generated and opened directly. Should not be saving onto the disk.
I tried the below code
protected void Button1_OnClick(object sender, EventArgs e)
{
Document myDoc = new Document(PageSize.A4.Rotate());
try
{
PdfWriter.GetInstance(myDoc, new FileStream(#"C:\Directory\Test.pdf", FileMode.Create));
myDoc.Open();
myDoc.Add(new Paragraph("Hello World"));
}
catch (DocumentException ex)
{
Console.Error.WriteLine(ex.Message);
}
myDoc.Close();
}
I also tried the below code which also generates the file on the Server which I dont want.
Document document = new Document(PageSize.A4);
PdfWriter.GetInstance(document, new FileStream(HttpContext.Current.Server.MapPath("~/Test.pdf"), FileMode.Create));
document.Open();
var WelcomePara = new Paragraph("Hello World");
document.Add(WelcomePara);
document.Close();
This one creates the pdf file on the desktop, I need it to be opened in the pdf format.Can someone help me please.
Almost every time that something accepts a FileStream is actually really accepts a generic System.IO.Stream object which FileStream is a subclass of. This means that you can instead use its cousin System.IO.MemoryStream which is what you are looking for:
byte[] bytes;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) {
using (iTextSharp.text.Document doc = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4.Rotate())) {
using (iTextSharp.text.pdf.PdfWriter w = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.NewPage();
doc.Add(new iTextSharp.text.Paragraph("Hello world"));
doc.Close();
bytes = ms.ToArray();
}
}
}
//Do whatever you want with the byte array here
You don't have to create the byte array if you don't want, I was just showing how to create a PDF and give you something ".net-like" for you to work with.
I was able to get it work finally.
using (var ms = new MemoryStream())
{
using (var document = new Document(PageSize.A4,50,50,15,15))
{
PdfWriter.GetInstance(document, ms);
document.Open();
document.Add(new Paragraph("HelloWorld"));
document.Close();
}
Response.Clear();
//Response.ContentType = "application/pdf";
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename= Test.pdf");
Response.Buffer = true;
Response.Clear();
var bytes = ms.ToArray();
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.OutputStream.Flush();
}
This Works for me.
using (var ms = new MemoryStream())
{
using (var document = new Document(PageSize.A4,50,50,15,15))
{
// step 2
PdfWriter writer = PdfWriter.GetInstance(document, ms);
// step 3
document.Open();
// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.Parse(new StringReader(--Your HTML--));
// step 5
document.Close();
}
Byte[] FileBuffer = ms.ToArray();
if (FileBuffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", FileBuffer.Length.ToString());
Response.BinaryWrite(FileBuffer);
}
}

iTextSharp appending table to document in memory stream after PDFStamper has been used

Hi I am trying to add a table to a pdf after I have used the stamper.
// CREATE MEMORY STRING
MemoryStream ms = new MemoryStream();
string formFile = Server.MapPath("testImg.pdf");
PdfReader reader = new PdfReader(formFile);
PdfStamper outStamper = new PdfStamper(reader, ms);
AcroFields fields = outStamper.AcroFields;
// UPDATE THE FORM FIELDS
fields.SetField("Text1", "John Smith");
fields.SetField("Text2", "1234567890");
fields.SetField("Text3", "1234567890");
//ADD LOGO
iTextSharp.text.Image headerlogo = iTextSharp.text.Image.GetInstance(Server.MapPath("logo.jpg"));
headerlogo.ScaleToFit(140, 399);
headerlogo.Alignment = iTextSharp.text.Image.UNDERLYING;
headerlogo.SetAbsolutePosition(200, 500);
int pageCount = reader.NumberOfPages;
PdfContentByte body = outStamper.GetOverContent(pageCount);
body.AddImage(headerlogo);
outStamper.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=test");
Response.Buffer = true;
Response.Clear();
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
Response.OutputStream.Flush();
Response.End();
I want to be able to append the document with a table.
PdfPTable table = new PdfPTable(3);
PdfPCell cell = new PdfPCell(new Phrase("Header spanning 3 columns"));
cell.Colspan = 3;
cell.BorderWidth = 5;
cell.HorizontalAlignment = 1; //0=Left, 1=Centre, 2=Right
table.AddCell(cell);
table.AddCell("Col 1 Row 1");
table.AddCell("Col 2 Row 1");
table.AddCell("Col 3 Row 1");
table.AddCell("Col 1 Row 2");
table.AddCell("Col 2 Row 2");
table.AddCell("Col 3 Row 2");
document.Add(table);
I am having trouble with defining the document to add the table to. Please can someone advise how I would add the table to the PDF in the Memory Stream.
Any help would be greatly appreciated.
Alex
Not sure how you have the two pieces working together but here is how I've done it for my application.
Basically i keep the stamping separate from adding structured content and then merging the results into one big pdf. You could try and do all of it together in one big step using table.WriteSelectedRows (which takes a PdfContentByte as one of its arguments) but the time that i have to spend with manual layouts, tends to outweigh the benefit of having it all done in one step (besides the fact that it becomes one huge method which is hard to maintain / reuse)
For clarification & testing purpose, I've used FileStream but of course, the same works fine with MemoryStream and reuse streams should you end up creating one monolithic function in your development code.
Here is my test application that I used to confirm the code and run your scenario:
Steps:
Create Test2.pdf (stamped contents
of original source) from Test.pdf
(our original source)
Create Test3.pdf (containing all our content to be appended at the end)
Open Test2.pdf & Test3.pdf and merge them into Test4.pdf final stream
Note: I haven't used image stamping code and you may have to adjust using on Document in first section if PdfStamper closes the underlying Document as well (can't recall if it does from top of my head but it will throw a helpful exception in case you need to adjust the using statement)
private static void Main(string[] args)
{
using (FileStream ms = new FileStream("C:\\Test2.pdf", FileMode.Create))
using (FileStream formFile = new FileStream("C:\\Test.pdf", FileMode.Open))
{
PdfReader reader = new PdfReader(formFile);
using (Document document = new Document(reader.GetPageSizeWithRotation(1)))
{
//PdfStamper outStamper = new PdfStamper(reader, ms);
//PdfContentByte body = outStamper.GetOverContent(reader.NumberOfPages);
//document.Open(); //Open document to work with
//AcroFields fields = outStamper.AcroFields;
//// UPDATE THE FORM FIELDS
//fields.SetField("Text1", "John Smith");
//fields.SetField("Text2", "1234567890");
//fields.SetField("Text3", "1234567890");
////ADD LOGO
//iTextSharp.text.Image headerlogo = iTextSharp.text.Image.GetInstance(Server.MapPath("logo.jpg"));
//headerlogo.ScaleToFit(140, 399);
//headerlogo.Alignment = iTextSharp.text.Image.UNDERLYING;
//headerlogo.SetAbsolutePosition(200, 500);
//body.AddImage(headerlogo);
//outStamper.Close();
}
}
using (FileStream ms = new FileStream("C:\\Test3.pdf", FileMode.Create))
using (FileStream formFile = new FileStream("C:\\Test2.pdf", FileMode.Open))
{
PdfReader reader = new PdfReader(formFile);
using (Document document = new Document(reader.GetPageSizeWithRotation(1)))
{
PdfWriter pdfWriter = PdfWriter.GetInstance(document, ms);
document.Open();
PdfPTable table = new PdfPTable(3);
PdfPCell cell = new PdfPCell(new Phrase("Header spanning 3 columns")) { Colspan = 3, BorderWidth = 5, HorizontalAlignment = 1 };
table.AddCell(cell);
table.AddCell("Col 1 Row 1");
table.AddCell("Col 2 Row 1");
table.AddCell("Col 3 Row 1");
table.AddCell("Col 1 Row 2");
table.AddCell("Col 2 Row 2");
table.AddCell("Col 3 Row 2");
table.CompleteRow(); //Added - table won't add the final row if its cells are incomplete - safe to have it ending a table
document.Add(table);
}
}
using (FileStream ms = new FileStream("C:\\Test4.pdf", FileMode.Create))
using (FileStream stampedfile = new FileStream("C:\\Test2.pdf", FileMode.Open))
using (FileStream appendfile = new FileStream("C:\\Test3.pdf", FileMode.Open))
{
PdfReader stampedContentReader = new PdfReader(stampedfile);
PdfReader appendContentReader = new PdfReader(appendfile);
using (Document document = new Document(stampedContentReader.GetPageSizeWithRotation(1)))
{
PdfCopy pdfCopy = new PdfCopy(document, ms);
document.Open();
for (int i = 1; i <= stampedContentReader.NumberOfPages; i++)
pdfCopy.AddPage(pdfCopy.GetImportedPage(stampedContentReader, i));
for (int i = 1; i <= appendContentReader.NumberOfPages; i++)
pdfCopy.AddPage(pdfCopy.GetImportedPage(appendContentReader, i));
}
}
}
Hope this helps.

Resources