UPDATE 31-03-2023:
In one of chrome's last updates some extra security measures were added and the solution bellow stoped working because the websocket connection could not be stablish. To fix this we added a new argument to ChromeDriver:
options.addArgument("--remote-allow-origins=*");
UPDATE 31-05-2021:
we noticed that the original workaround was not always working properly, and we went for a Selenium + ChromeDriver:
public void generatePdf(Path inputPath, Path outputPath) throws Exception
{
try
{
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless", "--disable-gpu", "--run-all-compositor-stages-before-draw");
ChromeDriver chromeDriver = new ChromeDriver(options);
chromeDriver.get(inputPath.toString());
Map<String, Object> params = new HashMap();
String command = "Page.printToPDF";
Map<String, Object> output = chromeDriver.executeCdpCommand(command, params);
try
{
FileOutputStream fileOutputStream = new FileOutputStream(outputPath.toString());
byte[] byteArray = java.util.Base64.getDecoder().decode((String) output.get("data"));
fileOutputStream.write(byteArray);
fileOutputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace(System.err);
throw e;
}
}
If this will be called frequently I suggest reusing the driver object because it takes a while to initialize.
Remember to close or quit the driver to avoid leaving Zombie chrome processes behind and also remember to install ChromeDriver in your machine.
Original Solution:
Not being able to get the desired outcome using ChromeDriver my workaround was to call the headless chrome in the command-line from my Java program.
This is working on Windows but just changing the contents of the paths used in the command variable should make it work in Linux too.
public void generatePdf(Path inputPath, Path outputPath) throws Exception {
try {
String chromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";
String command = chromePath + " --headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf=" + outputPath.toString() + " " + inputPath.toString();
// Runs "chrome" Windows command
Process process = Runtime.getRuntime().exec(command);
process.waitFor(); // Waits for the command's execution to finish
}catch (Exception e){
e.printStackTrace(System.err);
throw e;
}finally{
// Deletes files on exit
input.toFile().deleteOnExit();
output.toFile().deleteOnExit();
}
}
Note: both input and output paths are temporary files created with NIO.