Генерация PDF-файлов Spring MVC

#java #spring-mvc #itext

#java #spring-mvc #itext

Вопрос:

У меня есть веб-приложение Java, основанное на Spring MVC. Задача состоит в том, чтобы сгенерировать файл pdf. Как всем известно, движок spring имеет собственную встроенную библиотеку iText, поэтому сгенерировать PDF-файл действительно просто. Прежде всего, нам нужно перегрузить AbstractView и создать некоторый PDFView. И вторая вещь заключается в том, чтобы использовать это представление в контроллере. Но в моем приложении я также должен иметь возможность сохранять сгенерированные PDF-файлы на локальном диске или предоставлять моим пользователям некоторую ссылку для загрузки этого файла. Таким образом, представление в этом случае мне не подходит.

Я хочу создать какой-нибудь универсальный генератор pdf, который создает PDF-файл и возвращает массив байтов. Таким образом, я могу использовать этот массив для хранения файлов (на жестком диске) или распечатать его непосредственно в браузере. И вопрос в том, есть ли какой-либо способ использовать такой движок (который возвращает только массив байтов) в решении PDFView? Я спрашиваю, потому что перегруженный метод buildPdfDocument (в PDFView) уже имеет параметры PdfWriter и Document. Спасибо

Ответ №1:

tldr; вы должны иметь возможность использовать представление и сохранять его в файл.

Попробуйте использовать Flying Saucer и его ITextRenderer при перегрузке AbstractPdfView.

 import org.xhtmlrenderer.pdf.ITextRenderer;
public class MyAbstractView extends AbstractView {
   OutputStream os;

   public void buildPdfDocument(Map<String,Object> model, com.lowagie.text.Document document, com.lowagie.text.pdf.PdfWriter writer, HttpServletRequest request, HttpServletResponse response){
   //process model params
   os = new FileOutputStream(outputFile);
   ITextRenderer renderer = new ITextRenderer();
   String url = "http://www.mysite.com"; //set your sample url namespace here
   renderer.setDocument(document, url); //use the passed in document
   renderer.layout();
   renderer.createPDF(os);
   os.close();
   }
}

protected final void renderMergedOutputModel(Map<String,Object> model,
                                         HttpServletRequest request,
                                         HttpServletResponse response)
                                  throws Exception{
 if(os != null){
  response.outputStream = os;
 }

public byte[] getPDFAsBytes(){
  if(os != null){
     byte[] stuff;
     os.write(stuff);
     return stuff;
  }
}
  

}

Вероятно, вам придется изменить показанный здесь пример реализации, но это должно обеспечить основную суть.

Комментарии:

1. Спасибо за ваш ответ. К сожалению, я не использую grails. Кто-нибудь знает, как это реализовать на «чистой» java spring?

2. Grails — это просто Spring MVC и другие материалы в Groovy, которые очень похожи на Java. Этот ответ предназначен для того, чтобы вы могли создать аналогичную функциональность, проверив исходный код библиотеки, который доступен по адресу svn.codehaus.org/grails-plugins/grails-rendering/trunk . Загрузите версию 0.3 и посмотрите конкретно на PdfRenderingService и его родительский класс, и вы увидите, что он по сути аналогичен чистой Java.

3. Для рендеринга просто используется Flying Saucer under the covers, в котором есть довольно хороший учебник о том, как вы могли бы использовать его специально для создания выходного потока. Проверьте ссылку.

4. Не могли бы вы предоставить какой-нибудь пример кода, как это выглядит в контроллере? Особенно та часть, где вы сохраняете представление в файле?

5. Контроллер — это просто класс, на который возложена конкретная ответственность за посредничество между моделями и представлениями. Следовательно, работа с файлами в нем должна работать так же, как и в любом другом классе, где вы записываете содержимое массива байтов в файл. Я уверен, что вы можете поискать в Google примеры написания файлов. Однако, как правило, эта работа должна выполняться в службе приложений , а не в контроллере. Контроллер должен делегировать службе (передавая массив байтов), которая обрабатывает эту операцию. Плагин для рендеринга был выбран потому, что он очень четко показывает, как добиться такого приятного разделения задач