Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Flying Saucer, how do I generate a pdf with a page number and page total on every page at the footer?

It took me a little more research than I would have liked to figure this out on my own, so I'm going to post a comprehensive answer here. It seems like the information to do this is spread across many different websites and I'd like to put it in one place. This answer may be the same thing, but my eyes glaze over because it's in a Java string and not in a html template. Here's the question:

I'm rendering a PDF and I want a footer at the bottom of the page that says, "Page n of m" where "n" is the page number you're on and "m" is the total pages in the document. How do I do that?

like image 920
Daniel Kaplan Avatar asked Jul 30 '13 17:07

Daniel Kaplan


5 Answers

In your html, you need to put this somewhere in the body tag:

<div id="footer">
    page <span id="pagenumber"></span> of <span id="pagecount"></span>
</div>

And this should be your css/style:

    #footer {
        position: running(footer);
        text-align: right;
    }

    @page {
        @bottom-right {
            content: element(footer);
        }
    }

    #pagenumber:before {
        content: counter(page);
    }

    #pagecount:before {
        content: counter(pages);
    }

You can learn more about that @bottom-right option here.

like image 92
Daniel Kaplan Avatar answered Oct 17 '22 23:10

Daniel Kaplan


You could also try a slightly more succinct approach:

@page {
  @bottom-right {
    content: "Page " counter(page) " of " counter(pages);
  }
}

You need to put this in your css/style, and you do not need to add an extra footer HTML element.

like image 42
John Mark Avatar answered Oct 18 '22 00:10

John Mark


@John Mark 's solution worked for me. In my application I needed to embed the style info in the HTML, so I wrapped this in <style> tags and put it inside the <head> before <title>. Maybe that info will be useful to someone else.

like image 30
Matt Morgan Avatar answered Oct 18 '22 00:10

Matt Morgan


Important Error & Solution!

For Starters, using John Mark's solution below is the CORRECT way to get it working:

@page {
  @bottom-right {
    content: "Page " counter(page) " of " counter(pages);
  }
}

However many people may have encountered the following issue where your PDF HAS STOPPED GENERATING!

This is solved by updating your VERSION of FLYING SAUCER.

I was running 9.1.4 when my PDF stopped generating due to the @page & @bottom-right css code.

This was a glitch in Flying Saucer that was fixed in version 9.1.5!

Make sure to update to 9.1.5 and use John Mark's answer.

like image 3
Adrian Higgins Avatar answered Oct 18 '22 01:10

Adrian Higgins


The most upvoted answer did not work for me, the footer only showed on the last page. (This behavior is also mentioned in the comments below the answer provided by Daniel Kaplan.)

The solution to this problem was provided by the following comment:

@PauloOliveira It shows only on the last page when the is too far down in the . Place it somewhere higher so that it will print before the first page ends. But John Mark's answer is better. – Edward Feb 3 '20 at 12:16

So what has worked for me (using FlyingSaucer rendering with OpenPDF) is the following - placing the definition of the footer element somewhere above the main content and applying the solution provided by Daniel Kaplan:

<body>
  <div id="header">Some header content</div>
  <div id="footer">
    page <span id="pagenumber"></span> of <span id="pagecount"></span>
  </div>
  <div th:each="item: ${listOfItems}">
    [The long content listing things over multiple pages...]
  </div>
</body>

And the CSS code:

@page {
    size: A4 portrait;
    margin-top: 2cm;
    margin-left: 2cm;
    margin-right: 2cm;
    margin-bottom: 3cm;

    @bottom-left {
        content: element(footer); /* footer element must be specified before end of first page! */
        vertical-align: top;
    }
}


#pagecount::after {
    content: counter(pages);
}

#pagenumber::after {
    counter-increment: page;
    counter-reset: page 1;

    content: counter(page);
}
like image 2
mattanja Avatar answered Oct 18 '22 01:10

mattanja