aelve
aelve

Reputation: 119

Groovy/Grails document download

I'm currently working on a web application using grails. One of the requirements is to generate excel timesheets and download it afterword. This is my code for downloading from grails controller.

response.contentType = "application/vnd.ms-excel"
response.setHeader("Content-Disposition","attachment;filename=name.xls")
response.outputStream << wb.bytes
response.outputStream.flush()

But my excel file is corrupted. I can open it using open office, but doesn't work using microsoft office or google drive. Looks like the content of the xls file is not well formatted. If I save document instead of downloading everything is ok.

 FileOutputStream fileOut = new FileOutputStream("name.xls")
 wb.write(fileOut)
 fileOut.close()

I cannot figured out why the file content is corrupted when downloaded as byte array.

Grails version - 2.3.7 Apache poi version - 3.13

Thanks in advance,

Method code

   def generate(){

    TimeSheetExportWrapper timeSheet = new TimeSheetExportWrapper()
    bindData(timeSheet, params.ts)

    HSSFWorkbook wb = excelExportService.createExcelTimeSheet(getCurrentTenant(), timeSheet, getCurrentTimezone())

    response.contentType = "application/vnd.ms-excel"
    response.setHeader("Content-Disposition", "attachment;filename=${timeSheet.proposedFileName}")
    response.outputStream << wb.bytes
    response.outputStream.flush()
}

Upvotes: 0

Views: 1332

Answers (1)

Joshua Moore
Joshua Moore

Reputation: 24776

There are a few things that you should be doing:

First, set the content length: response.setHeader("Content-Length", "${wb.bytes.length}")

Secondly, close the output: response.outputStream.close()

And finally, make sure you return null to ensure Grails does not attempt to render a view.

   def generate(){

    TimeSheetExportWrapper timeSheet = new TimeSheetExportWrapper()
    bindData(timeSheet, params.ts)

    HSSFWorkbook wb = excelExportService.createExcelTimeSheet(getCurrentTenant(), timeSheet, getCurrentTimezone())

    response.contentType = "application/vnd.ms-excel"
    response.setHeader("Content-Length", "${wb.bytes.length}")
    response.setHeader("Content-Disposition", "attachment;filename=${timeSheet.proposedFileName}")
    response.outputStream << wb.bytes
    response.outputStream.flush()
    response.outputStream.close()
    return null
}

Upvotes: 1

Related Questions