
En nuestra organización utilizamos Chrome sin cabeza para convertir páginas web a archivos PDF. Tenemos una aplicación Java especial para eso, que utiliza el siguiente cliente CDT para iniciar las instancias de Chrome y comunicarse con ellas:https://github.com/kklisura/chrome-devtools-java-client En la mayoría de los casos, todo funciona como se esperaba y obtenemos nuestros archivos PDF, pero para algunas páginas web, Headless-Chrome simplemente se bloquea durante el paso de impresión del PDF. Ejemplo de dicha página:
https://www.idc.com/cee/events/64662-web-developers-event-for-automatic-tests-on-idc-com-do-not-update-manually/print-agenda
No pudimos obtener ningún registro útil de las instancias sin cabeza de Chrome, aunque seguimos todos los pasos necesarios que se especifican aquí:https://www.chromium.org/for-testers/enable-logging Intentamos depurar esas instancias sin cabeza usando la opción --remote-debugging-port, pero no encontramos nada sospechoso en la consola ni en ningún otro lugar. La página pareció cargarse correctamente y parece que Chrome simplemente se negó a imprimir las páginas.
¿Alguien más tuvo problemas similares? ¿O tal vez alguien tiene alguna idea de por qué sucede esto? ¿Quizás alguien tenga algunos consejos sobre cómo habilitar el registro en instancias sin cabeza de Chrome? Estaremos agradecidos por cualquier ayuda.
Aquí están las versiones de las aplicaciones:
Google Chrome: 76.0.3809.100
chrome-devtools-java-client: 1.3.5
¡Gracias! Máx.
Respuesta1
Este problema es causado por la implementación subyacente de la API websocket, Tyrus. Tiene untamaño máximo de mensaje predeterminado de 4 MB. Esta URL, y muchas otras (especialmente si habilita la impresión de fondos), dan como resultado archivos PDF que (cuando se codifican como base 64) superan ese límite de 4 MB. En este caso el websocket se cierra con unError de desbordamiento del búfer, sin embargo no lo vemos comochrome-devtools-java-client
no escucha los onClose
eventos del websocket.
Puedes resolver este problema transmitiendo el resultado de la impresión...
Pase el PrintToPDFTransferMode.RETURN_AS_STREAM
como transferMode
parámetro Page.printToPdf
y luego lea desde la transmisión con un búfer significativamente menor que el límite de 4 MB (incluso después del aumento debido a la base 64). Yo uso 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());
No estoy seguro del offset
tratamiento en el caso de que el resultado no esté codificado en base 64, ¡pero no creo que veamos eso al imprimir!