Search code examples
web.xmlscalatra

Download Excel as xlsx instead of zip format in Scalatra


I'm writing the Excel Workbook created using Apache POI to the response object directly as follows without creating a file:

val outputStream: ByteArrayOutputStream = new ByteArrayOutputStream()
workbook.write(outputStream)
ExcelOk(response.getOutputStream.write(outputStream.toByteArray))

But once the size of the response exceeds 8kB, it starts getting downloaded as zip file in Chrome and as octet-stream in FireFox.

My ExcelOk object looks like this:

object ExcelOk {
  def apply(body: Any = Unit, headers: Map[String, String] = ExcelContentType, reason: String = "") = {
    halt(ActionResult(responseStatus(200, reason), body, headers ))
  }
}

and my ExcelContentType(i.e, response headers) is as below:

val ExcelContentType = Map(
  "Access-Control-Allow-Credentials" -> "true",
  "Access-Control-Allow-Methods" -> "GET, PUT, POST, DELETE, OPTIONS",
  "Access-Control-Allow-Origin" -> "*",
  "Access-Control-Max-Age" -> "1728000",
  "Content-type" -> "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "Content-disposition" -> "attachment; filename=excel_report.xlsx"
)

I even tried adding "Transfer-Encoding" -> "chunked" to the header list but it doesn't work.

I added this snippet in my web.xml file as well but it didn't help either:

<mime-mapping>
  <extension>xlsx</extension>
  <mime-type>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</mime-type>
</mime-mapping>

Any help regarding this would be useful. Note that this behavior is observed only after response size exceeds certain threshold.


Solution

  • You have to set response headers before writing content to response output stream.

    response.setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    response.setHeader("Content-disposition", "attachment; filename=excel_report.xlsx")
    
    workbook.write(response.getOutputStream)