Update ConvertHtmlToPdfAction to use openhtmltopdf instead of flying-saucer-pdf-openpdf (gaining support for min/max-width/height

This commit is contained in:
2025-03-27 11:55:36 -05:00
parent d0508c2568
commit 16cedfeb6e
2 changed files with 43 additions and 28 deletions

View File

@ -151,16 +151,21 @@
<version>2.3</version> <version>2.3</version>
</dependency> </dependency>
<!-- the next 2 deps are for html to pdf - per https://www.baeldung.com/java-html-to-pdf --> <!-- the next 3 deps are for html to pdf -->
<dependency> <dependency>
<groupId>org.jsoup</groupId> <groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId> <artifactId>jsoup</artifactId>
<version>1.15.3</version> <version>1.15.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.xhtmlrenderer</groupId> <groupId>com.openhtmltopdf</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId> <artifactId>openhtmltopdf-core</artifactId>
<version>9.1.22</version> <version>1.0.10</version>
</dependency>
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.10</version>
</dependency> </dependency>
<!-- the next 3 deps are being added for google drive support --> <!-- the next 3 deps are being added for google drive support -->

View File

@ -26,22 +26,31 @@ import java.nio.file.Path;
import java.util.Map; import java.util.Map;
import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction; import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfInput; import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfInput;
import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfOutput; import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfOutput;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.openhtmltopdf.css.constants.IdentValue;
import com.openhtmltopdf.pdfboxout.PdfBoxFontResolver;
import com.openhtmltopdf.pdfboxout.PdfBoxRenderer;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.pdf.ITextRenderer;
/******************************************************************************* /*******************************************************************************
** Action to convert a string of HTML to a PDF! ** Action to convert a string of HTML to a PDF!
** **
** Much credit to https://www.baeldung.com/java-html-to-pdf ** Much credit to https://www.baeldung.com/java-html-to-pdf
*******************************************************************************/ **
** Updated in March 2025 to go from flying-saucer-pdf-openpdf lib to openhtmltopdf,
** mostly to get support for max-height on images...
********************************************************************************/
public class ConvertHtmlToPdfAction extends AbstractQActionFunction<ConvertHtmlToPdfInput, ConvertHtmlToPdfOutput> public class ConvertHtmlToPdfAction extends AbstractQActionFunction<ConvertHtmlToPdfInput, ConvertHtmlToPdfOutput>
{ {
private static final QLogger LOG = QLogger.getLogger(ConvertHtmlToPdfAction.class);
/******************************************************************************* /*******************************************************************************
** **
@ -62,31 +71,32 @@ public class ConvertHtmlToPdfAction extends AbstractQActionFunction<ConvertHtmlT
////////////////////////////// //////////////////////////////
// convert the XHTML to PDF // // convert the XHTML to PDF //
////////////////////////////// //////////////////////////////
ITextRenderer renderer = new ITextRenderer(); PdfRendererBuilder builder = new PdfRendererBuilder();
SharedContext sharedContext = renderer.getSharedContext(); builder.toStream(input.getOutputStream());
sharedContext.setPrint(true); builder.useFastMode();
sharedContext.setInteractive(false); builder.withHtmlContent(document.html(), input.getBasePath() == null ? "./" : input.getBasePath().toUri().toString());
if(input.getBasePath() != null) try(PdfBoxRenderer pdfBoxRenderer = builder.buildPdfRenderer())
{ {
String baseUrl = input.getBasePath().toUri().toURL().toString(); pdfBoxRenderer.layout();
renderer.setDocumentFromString(document.html(), baseUrl); pdfBoxRenderer.getSharedContext().setPrint(true);
} pdfBoxRenderer.getSharedContext().setInteractive(false);
else
{
renderer.setDocumentFromString(document.html());
}
////////////////////////////////////////////////// for(Map.Entry<String, Path> entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet())
// register any custom fonts the input supplied // {
////////////////////////////////////////////////// LOG.warn("Note: Custom fonts appear to not be working in this class at this time...");
for(Map.Entry<String, Path> entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet()) pdfBoxRenderer.getFontResolver().addFont(
{ entry.getValue().toAbsolutePath().toFile(), // Path to the TrueType font file
renderer.getFontResolver().addFont(entry.getValue().toAbsolutePath().toString(), entry.getKey(), "UTF-8", true, null); entry.getKey(), // Font family name to use in CSS
} 400, // Font weight (e.g., 400 for normal, 700 for bold)
IdentValue.NORMAL, // Font style (e.g., NORMAL, ITALIC)
true, // Whether to subset the font
PdfBoxFontResolver.FontGroup.MAIN // ??
);
}
renderer.layout(); pdfBoxRenderer.createPDF();
renderer.createPDF(input.getOutputStream()); }
return (output); return (output);
} }