
Em nossa organização, usamos headless-chrome para converter páginas da web em PDFs. Temos um aplicativo Java especial para isso, que utiliza o seguinte cliente CDT para iniciar as instâncias do Chrome e se comunicar com elas:https://github.com/kklisura/chrome-devtools-java-client Na maioria dos casos, tudo funciona conforme o esperado e obtemos nossos PDFs, mas para algumas páginas da web o headless-chrome simplesmente trava durante a etapa de impressão do PDF. Exemplo de tal página:
https://www.idc.com/cee/events/64662-web-developers-event-for-automatic-tests-on-idc-com-do-not-update-manually/print-agenda
Não conseguimos obter nenhum log útil das instâncias headless do Chrome, embora tenhamos seguido todas as etapas necessárias especificadas aqui:https://www.chromium.org/for-testers/enable-logging Tentamos depurar essas instâncias headless usando a opção --remote-debugging-port, mas não encontramos nada suspeito no console ou em qualquer outro lugar. A página parece ter sido carregada com sucesso e parece que o Chrome simplesmente se recusou a imprimir as páginas.
Alguém mais teve problemas semelhantes? Ou talvez alguém tenha alguma ideia de por que isso acontece? Talvez alguém tenha algumas dicas sobre como habilitar o log nas instâncias headless do Chrome? Ficaremos gratos por qualquer ajuda.
Aqui estão as versões dos aplicativos:
Google Chrome: 76.0.3809.100
chrome-devtools-java-client: 1.3.5
Obrigado! Máx.
Responder1
Esse problema é causado pela implementação subjacente da API do websocket, Tyrus. Tem umtamanho máximo padrão da mensagem de 4 MB. Este URL, e muitos outros (especialmente se você ativar a impressão de planos de fundo), resulta em PDFs que (quando codificados como base 64) são maiores que o limite de 4 MB. Neste caso o websocket é fechado com umErro de estouro de buffer, porém não vemos isso comochrome-devtools-java-client
não escuta os onClose
eventos do websocket.
Você pode resolver esse problema transmitindo o resultado da impressão...
Passe the PrintToPDFTransferMode.RETURN_AS_STREAM
como transferMode
parâmetro para Page.printToPdf
e depois leia o fluxo com um buffer significativamente menor que o limite de 4 MB (mesmo após o aumento devido à base 64). Eu uso 1MB:
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());
Não tenho certeza sobre o offset
tratamento no caso em que o resultado não esteja codificado na base 64, mas não acho que veremos isso na impressão!