I'm trying to use the rendering plugin to save a generated pdf to a file when a controller action to generate a PDF is shown. I'm following the instructions per: http://gpc.github.com/grails-rendering/docs/manual/index.html
def pdf = {
def project = Project.get(params.id)
def numGoodMilestones = queryService.getGoodShapeMilestonesCount(project)
def totalMilestones = project.milestones.size()
def updateHistory = queryService.getReadableHistory(project)
def summaryName = "${project.name.replace(" ","_")}_summary_${String.format('%tF', new Date()).replace(" ","_")}"
if(!project)
{
flash.message = g.message(code:'default.not.found.message',
args:[message(code:'project.label',default:'Project'),params.id])
redirect(uri:'/')
}
// see if a summary has been generated with this data and attached to the
// project. If not, do it.
def existingAttachedSummary = ProjectDocument.findByName(summaryName)
if(!existingAttachedSummary)
{
//make the file
def savedSummary = new File(summaryName).withOutputStream { outputStream ->
pdfRenderingService.render( controller:this,
template: "projectDetail",
model:[project:project,
numGoodMilestones:numGoodMilestones,
totalMilestones:totalMilestones,
updateHistory: updateHistory])
}
def projectDocument = new ProjectDocument(name:summaryName,
description:"Project summary automatically generated on ${new Date()}}",
fileData:savedSummary,
开发者_运维知识库 owner: springSecurityService.currentUser,
project:project
)
if(projectDocument.validate())
{
projectDocument.save(flush:true)
flash.message="I saved a document, yo. ${projectDocument}."
}
else
{
flash.message="Errors, yo. ${projectDocument.errors.allErrors.each{ it }}."
}
}
else
{
flash.message = "project summary already attached to project"
}
renderPdf(template: "projectDetail",
model:[project:project, numGoodMilestones:numGoodMilestones, totalMilestones:totalMilestones, updateHistory: updateHistory],
filename: "${summaryName}.pdf")
}
The renderPdf() method works fine, as the output in my browser is what is expected. But when I go look at the created ProjectDocument, I see a blank PDF file. I'm trying to save to a file in the exact same way described by the rendering documentation. What am I doing wrong?
I think this is an error in the docs. Pass your outputStream as the last argument to pdfRenderingService.render
.
def savedSummary = new File(summaryName).withOutputStream { outputStream ->
pdfRenderingService.render( controller:this,
template: "projectDetail",
model:[project:project,
numGoodMilestones:numGoodMilestones,
totalMilestones:totalMilestones,
updateHistory: updateHistory],
outputStream) // <- added this parameter
}
A little late on the game here but the samples in the docs are misleading. I also tried
new File("report.pdf").withOutputStream { outputStream ->
outputStream << pdfRenderingService.render(template: '/report/report', model: [serial: 12345])
}
Which created a blank PDF. Mind you it wasn't zero bytes - there was data in the file but it was a blank PDF. The issue is that the method signature takes a map and an output stream whereas the sample shows this:
pdfRenderingService.render(template: '/report/report', model: [serial: 12345])
It should be this :
pdfRenderingService.render([template: '/report/report', model: [serial: 12345]], new File("report.pdf").newOutputStream())
Then your PDF will have content.
I think the sample is trying to show the renderPDF method signature or... ah well who needs samples anyway right?
Hopefully this will help others.
I tried all of the above solutions.. but one thing was missing "toByteArray()":
def mypdf = new ByteArrayOutputStream().withStream { outputStream ->
pdfRenderingService.render(
[controller:this,
template: "pdf",
model:[form:formInstance]],
outputStream // <- ataylor added this parameter
).toByteArray() // <- I added this
}
Now you can store it and use it later like this:
response.contentType = 'application/pdf'
response.setHeader 'Content-disposition', "attachment; filename=\"${formInstance.name}.pdf\"" // comment this to open in browser
response.outputStream << mypdf
response.outputStream.flush()
For me its works the next script for grails 2.5.0
// Render to a file
// rendering 2.5.0
def pdf = new ByteArrayOutputStream().withStream { outputStream ->
pdfRenderingService.render(
[controller:this,
template: "printReporte",
model: [reporteCufinInstance: reporteCufinInstance, numAnios: columnas]],
outputStream // <- in the documentation use the outputstream http://gpc.github.io/grails-rendering/guide/single.html#5.%20Rendering%20To%20The%20Response
).toByteArray() // <- parse to byteArray for render file
}
render(file:pdf,contentType: 'application/pdf')
Thanks guys
精彩评论