Reputation: 119
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
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