Search code examples
c#pdf-generationitextitextpdf

How to generate mutiple page using PdfWriter


I am generating pdf file for payslip using PdfWriter in C#. And I'm downloading the pdf file from html code, every user it will create a table (<table>...</table>) and every table display in new page. But all table are displayed in same page.

eg

Page 1
Employee 1 Details
may the details will come to the next page.

Page 2
Employee 2 Details

Page 3
Employee 2 details
Page 4
Employee 3 details

.....
.....
....

But Now my output will come
Page 1
Employee 1
Employee 2
Page 2
Employee 3
Employee 4
Employee 5
.....

My code is

StringBuilder stb = new StringBuilder();
stb.Append(All.ToString());
EXP.InnerHtml = stb.ToString();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + filename + ".pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);

StringWriter stringWriter = new StringWriter();
HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);


string resHtml = "";

for(int i=0;i<10;i++)
{
    resHtml+="<table width='100%'><tr><td align='center'>payslip"+ i+"</td></tr></table>"; 
}
StringReader stringReader = new StringReader(resHtml);
Doc = new Document(PageSize.A2, 10f, 10f, 50f, 20f);

HTMLWorker htmlparser = new HTMLWorker(Doc);
PdfWriter.GetInstance(Doc, Response.OutputStream);
Doc.Open();
htmlparser.Open(); 
htmlparser.Parse(stringReader);
htmlparser.Close();
Doc.Close();
Response.Write(Doc);
Response.End();

Solution

  • You are using HTMLWorker. That class is deprecated: it is no longer supported as it has been abandoned in favor of XML Worker. There are different ways to solve your problem.

    Create multiple small HTML files instead of one big HTML

    I wouldn't create one long table for every employee, but a single table for every employee, and introduce document.NewPage() after adding every table. See Answer #2 to the question How to parse multiple HTML files into a single PDF?

    This is some Java code (you can read it as if it were pseudo code):

    public void createPdf(Employees employees) throws IOException, DocumentException {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(file));
        document.open();
        String css = readCSS();
        for (Employee employee : employees) {
            String html = createHtml(employee);
            ElementList list = XMLWorkerHelper.parseToElementList(html, css);
            for (Element e : list) {
                document.add(e);
            }
            document.newPage();
        }
        document.close();
    }
    

    This solution is the best solution from the point of view of memory and CPU use.

    Create one big HTML and introduce page breaks

    Another option is to introduce a page break before every employee table. See set new page in HTML using iTextSharp HTMLWorker (html to pdf)

    This isn't a good idea as you build up a large chunk of data in memory and that memory can only be released after the PDF is rendered. iTextSharp tries to flush pages to the OutputStream as soon as possible. If you create small HTML files, and add them to the PDF immediately, you can discard the HTML bytes from memory sooner rather than later and iTextSharp will also be able to flush content streams to the output, releasing memory that is needed to store that content.

    Important notice:

    Obviously, these answers imply that you do the right thing. That is: throw away your code that relies on the abandoned HTMLWorker and start using XML Worker.