Olá!
Bem, compartilhando uma dica interessante, que pode ajudar várias pessoas: Geração de PDF através das view GSPs de uma aplicação Grails. E o que é melhor: em 5 minutos!!
Então vamos lá:
1) Baixe o pacote Flying Saucer: https://xhtmlrenderer.dev.java.net/
2) Dentro do pacote, você encontrará dois arquivos: core-renderer.jar
e iText-2.0.8.jar
– Adicione estes arquivos dentro do diretório lib
da sua aplicação Grails
3) Imagine uma aplicação Biblioteca, onde você deseja exportar a visualização das informações de um livro através de um arquivo pdf. Definindo uma URL de acesso a esta funcionalidade, podemos criar o link:
http://seudominio.net/book/<CODIGO>/pdf
Nossa classe “Book”:
class Book { String title String author String description int year static constraints = { title blank:false author blank:false year nullable:true description nullable:true } }
O Pdf que vamos gerar será um arquivo html simples, salvo como o template grails-app/views/book/_pdf.gsp
:
${book.title}
${book.author}, ${book.year}
${book.description}
Até ai nada de novo. (Para deixar a coisa mais chique, leia sobre Content Negotiation em Grails – mas para este exemplo 5 minutos, isso tá otimo)
4) O processo de geração do PDF será:
- Extrair o resultado de uma view para uma String
- Invocar o Flying Saucer/iText para que a mágica aconteça
- Retornar o Arquivo para o usuário
Para isso, a action pdf, dentro do controller BookController será implementada assim:
def toPdf = { def baseUri = request.scheme + "://" + request.serverName + ":" + request.serverPort + grailsAttributes.getApplicationUri(request) // Rendering View def book = Book.get(params.id) def render_result = g.render(template:"/book/pdf.gsp", model: [book: book]) // creating PDF ByteArrayOutputStream baos = new ByteArrayOutputStream(); ITextRenderer renderer = new ITextRenderer(); byte[] b renderer.setDocumentFromString(render_result.toString(), baseUri); renderer.layout(); renderer.createPDF(baos); b = baos.toByteArray(); // Sending file to the user response.setContentType("application/pdf") response.setHeader("Content-disposition", "attachment; filename=${book.title}.pdf") response.setContentLength(b.length) response.getOutputStream().write(b) }
Pronto! Está Feito!
Considerações
- Transforme a geração do PDF em um serviço dentro da sua aplicação, deixando o código mais organizado e com uma melhor performance
- É possível generalizar o código acima para funcionar com mais objetos do domínio, ampliando reuso, separando as responsabilidade de rendering da view e escrita do arquivo no response através de classes separadas. O PDF Plugin citado abaixo pode te dar algumas ideias
- Possui algum comentário sobre a solucao acima? Comente!!
Aprofundando o seu conhecimento sobre o tema
- Generating PDF for Fun and Profit with Flying Saucer and iText
- Solução proposta pelo Aaron Eischeid através do PDF Plugin for Grails
- iText Homepage (Versao opensource disponível no sourceforge)