
В нашей организации мы используем headless-chrome для конвертации веб-страниц в PDF-файлы. У нас есть специальное Java-приложение для этого, которое использует следующий клиент CDT для запуска экземпляров chrome и связи с ними:https://github.com/kklisura/chrome-devtools-java-client В большинстве случаев все работает как надо, и мы получаем наши PDF, но для некоторых веб-страниц headless-chrome просто зависает на этапе печати PDF. Пример такой страницы:
https://www.idc.com/cee/events/64662-web-developers-event-for-automatic-tests-on-idc-com-do-not-update-manually/print-agenda
Нам не удалось получить никаких полезных журналов от headless-экземпляров Chrome, хотя мы выполнили все необходимые шаги, указанные здесь:https://www.chromium.org/for-testers/enable-logging Мы попытались отладить эти headless-экземпляры с помощью опции --remote-debugging-port, но не нашли ничего подозрительного в консоли или где-либо еще. Страница, похоже, была успешно загружена, и похоже, что Chrome просто отказался печатать страницы.
У кого-то были похожие проблемы? Или, может быть, у кого-то есть идеи, почему это происходит? Может быть, у кого-то есть советы, как включить ведение журнала на headless-экземплярах Chrome? Мы будем благодарны за любую помощь.
Вот версии приложений:
Google Chrome: 76.0.3809.100
chrome-devtools-java-client: 1.3.5
Спасибо! Макс.
решение1
Эта проблема вызвана базовой реализацией API вебсокета, Tyrus. Она имеетмаксимальный размер сообщения по умолчанию 4 МБ. Этот URL и многие другие (особенно если вы включите печать фонов) приводят к PDF-файлам, которые (при кодировании в base 64) превышают этот предел в 4 МБ. В этом случае веб-сокет закрывается с помощьюОшибка переполнения буфера, однако мы не видим этого какchrome-devtools-java-client
onClose
не прослушивает события вебсокета.
Эту проблему можно решить, передав результат печати в потоковом режиме...
Передайте PrintToPDFTransferMode.RETURN_AS_STREAM
в качестве transferMode
параметра Page.printToPdf
и затем считывайте из потока с буфером, значительно меньшим, чем ограничение в 4 МБ (даже после увеличения из-за base 64). Я использую 1 МБ:
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());
Я не уверен насчет offset
обработки в случае, когда результат не закодирован в формате base 64, но не думаю, что мы увидим это при печати!