Диалоговое окно печати Pdf-печать с помощью iText

65
6

Я использую iText для создания PDF файла и распечатываю его, используя следующий код:

Document iText_xls_2_pdf = new Document(PageSize.A4.rotate());
PdfWriter writer = PdfWriter.getInstance(iText_xls_2_pdf, response.getOutputStream());
iText_xls_2_pdf.open();

PdfAction action = new PdfAction(PdfAction.PRINTDIALOG);
writer.setOpenAction(action);
iText_xls_2_pdf.close();

Он отлично работает в первый раз, т.е. открывает диалоговое окно печати, как ожидалось. Когда пользователь закрывает диалоговое окно печати и снова вызывает тот же код, он ничего не делает.

Я здесь что-то не так?

Примечание. Я выполняю эту операцию в doGet методе сервлета.

спросил(а) 2021-01-19T18:38:02+03:00 9 месяцев назад
1
Решение
102

Сначала это: код, который вы используете для добавления открытого действия, является правильным. Любой просмотрщик PDF, который открывает создаваемый PDF-документ, должен запустить диалоговое окно печати.

Вы знаете, что ваш iText-код прав, потому что он работает при первом открытии PDF файла. В вашем случае это происходит в браузере. Неясно, какой PDF-просмотрщик используется: pdf.js в Firefox? Chrome PDF Viewer? Предварительный просмотр на Apple? Adobe Reader?

Примечание: вы не должны предполагать, что каждый просмотрщик PDF реализует полную спецификацию PDF. Некоторые зрители игнорируют открытое действие, другие даже не знают, что такое действие PrintDialog.

Вы пишете: как только пользователь закрывает диалоговое окно печати и снова вызывает тот же код, он ничего не делает.

Это странный способ поместить вещи. Пользователь не запускает код. Действие инициируется действием open, а не нажатием какой-либо кнопки или выбором какой-либо опции меню. Это поможет, если вы объясните, что вы имеете в виду, когда говорите: "снова вызывает тот же код".

Пока же предположим, что "вызов того же кода снова" эквивалентен обновлению/перезагрузке страницы. В этом случае возможно, что PDF никогда не открывается повторно, поскольку он еще не истек. Возможно, программа просмотра PDF в вашем браузере говорит: "Эй, документ, который я показываю сейчас, это тот же самый документ, который у меня есть в моем кеше. Мне не нужно его снова открывать". И если документ никогда не возобновляется, нет причин снова запускать открытое действие.

Когда вы загружаете PDF в браузер, какие заголовки вы настраиваете?

Можете ли вы попробовать добавить эти строки в соответствующее место в методе doGet():

response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/pdf");
response.setContentLength(baos.size());

Обратите внимание: baos - это ByteArrayOutputStream. Это неправильно:

PdfWriter writer = PdfWriter.getInstance(iText_xls_2_pdf, response.getOutputStream());

Вы должны сделать это следующим образом:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(iText_xls_2_pdf, baos);
// do a lot of other stuff

В OutputStream (особенно после установки заголовков) вы записываете содержимое в OutputStream объекта response:

OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();

См. Официальные часто задаваемые вопросы. Как я могу служить PDF в браузере, не сохраняя файл на стороне сервера?

Если все это не помогает, ваша проблема вызвана чем-то на стороне клиента. В этом случае на ваш вопрос нет ответа. Мы можем только сказать вам, что вы не делаете ничего плохого. Это правильный способ добавления открытого действия:

PdfAction action = new PdfAction(PdfAction.PRINTDIALOG);
writer.setOpenAction(action);

Если это не сработает, единственным ответом, который вы можете получить на Stack Overflow, будет: "Вы правильно поняли код" (при условии, что вы следуете советам ByteArrayOutputStream и HTTP-заголовкам).

ответил(а) 2021-01-19T18:38:02+03:00 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема