
In unserer Organisation verwenden wir Headless-Chrome zum Konvertieren von Webseiten in PDFs. Wir haben dafür eine spezielle Java-Anwendung, die den folgenden CDT-Client zum Starten der Chrome-Instanzen und zur Kommunikation mit ihnen verwendet:https://github.com/kklisura/chrome-devtools-java-client In den meisten Fällen funktioniert alles wie erwartet und wir erhalten unsere PDFs, aber bei einigen Webseiten bleibt headless-chrome beim PDF-Drucken einfach hängen. Beispiel für eine solche Seite:
https://www.idc.com/cee/events/64662-web-developers-event-for-automatic-tests-on-idc-com-do-not-update-manually/print-agenda
Wir konnten keine nützlichen Protokolle von den Headless-Instanzen von Chrome abrufen, obwohl wir alle hier angegebenen erforderlichen Schritte befolgt haben:https://www.chromium.org/for-testers/enable-logging Wir haben versucht, diese Headless-Instanzen mit der Option --remote-debugging-port zu debuggen, aber wir haben weder in der Konsole noch sonst irgendwo etwas Verdächtiges gefunden. Die Seite schien erfolgreich geladen worden zu sein und es scheint, dass Chrome sich einfach geweigert hat, die Seiten zu drucken.
Hatte jemand anderes ähnliche Probleme? Oder hat vielleicht jemand eine Idee, warum das passiert? Vielleicht hat jemand Tipps, wie man die Protokollierung in den Headless-Instanzen von Chrome aktiviert? Wir sind für jede Hilfe dankbar.
Hier sind die Versionen der Anwendungen:
Google Chrome: 76.0.3809.100
chrome-devtools-java-client: 1.3.5
Danke! Max.
Antwort1
Dieses Problem wird durch die zugrunde liegende WebSocket-API-Implementierung Tyrus verursacht. Es hat eineStandardmäßige maximale Nachrichtengröße von 4 MB. Diese URL und viele andere (insbesondere wenn Sie das Drucken von Hintergründen aktivieren) führen zu PDFs, die (bei Kodierung als Base 64) größer als die 4-MB-Grenze sind. In diesem Fall wird der WebSocket mit einemPufferüberlauffehler, aber wir sehen es nicht alschrome-devtools-java-client
hört nicht auf die onClose
Ereignisse des WebSockets.
Sie können dieses Problem lösen, indem Sie stattdessen das Druckergebnis streamen ...
Übergeben Sie dies PrintToPDFTransferMode.RETURN_AS_STREAM
als transferMode
Parameter Page.printToPdf
und lesen Sie dann aus dem Stream mit einem Puffer, der deutlich kleiner ist als das 4-MB-Limit (selbst nach der Erhöhung durch Base 64). Ich verwende 1 MB:
private static final int READ_BUFFER_SIZE = 1048576;
final PrintToPDF printToPDF = page.printToPDF(..., PrintToPDFTransferMode.RETURN_AS_STREAM);
final IO io = devToolsService.getIO();
int offset = 0;
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
do {
final Read read = io.read(printToPDF.getStream(), offset, READ_BUFFER_SIZE);
if (read.getBase64Encoded() == Boolean.TRUE) {
byte[] decode = Base64.getDecoder().decode(read.getData());
offset += decode.length;
fos.write(decode);
} else {
byte[] decode = read.getData().getBytes(StandardCharsets.UTF_8);
offset += decode.length;
fos.write(decode);
}
if (read.getEof() == Boolean.TRUE) {
break;
}
} while (true);
}
io.close(printToPDF.getStream());
Ich bin mir nicht sicher, wie es offset
mit dem Ergebnis aussieht, wenn es nicht Base64-codiert ist, aber ich glaube nicht, dass wir das beim Drucken sehen werden!