
在我們的組織中,我們使用 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
儘管我們遵循了此處指定的所有必要步驟,但我們無法從 chrome 的無頭實例中取得任何有用的日誌:https://www.chromium.org/for-testers/enable-logging 我們嘗試使用 --remote-debugging-port 選項來偵錯這些無頭實例,但我們在控制台或其他任何地方沒有發現任何可疑的內容。該頁面似乎已成功加載,並且 chrome 似乎只是拒絕列印頁面。
其他人有類似的問題嗎?或者也許有人知道為什麼會發生這種情況?也許有人有一些關於如何在 chrome 無頭實例上啟用日誌記錄的提示?我們將不勝感激任何幫助。
以下是應用程式的版本:
Google Chrome: 76.0.3809.100
chrome-devtools-java-client: 1.3.5
謝謝!最大限度。
答案1
該問題是由底層 websocket API 實作 Tyrus 引起的。它有一個預設最大訊息大小為 4MB。此 URL 以及許多其他 URL(特別是如果您啟用列印背景)會導致 PDF(編碼為 Base 64 時)大於 4MB 限制。在這種情況下,websocket 被關閉緩衝區溢位錯誤,但是我們不認為它是chrome-devtools-java-client
不監聽 websocket 的onClose
事件。
您可以透過串流列印結果來解決此問題...
PrintToPDFTransferMode.RETURN_AS_STREAM
將參數傳遞transferMode
給Page.printToPdf
流,然後從緩衝區讀取明顯小於 4MB 限制的流(即使在由於基數 64 而增加之後)。我用的是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());
我不確定offset
結果不是 Base 64 編碼的情況下的處理方式,但我認為我們在列印時不會看到這種情況!