在 Scalatra 中下载 Excel 为 xlsx 而不是 zip 格式

Download Excel as xlsx instead of zip format in Scalatra

我正在将使用 Apache POI 创建的 Excel 工作簿直接写到响应 object 中,而不创建文件:

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

但是一旦响应的大小超过 8kB,它就会开始在 Chrome 中下载为 zip 文件,在 FireFox 中下载为 octet-stream

我的 ExcelOk object 看起来像这样:

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

和我的 ExcelContentType(即响应 headers)如下:

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"
)

我什至尝试将 "Transfer-Encoding" -> "chunked" 添加到 header 列表,但它不起作用。

我也在我的 web.xml 文件中添加了这个片段,但它也没有帮助:

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

有关此的任何帮助都会很有用。请注意,只有在响应大小超过特定阈值后才会观察到此行为。

在将内容写入响应输出流之前,您必须设置响应 headers。

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

workbook.write(response.getOutputStream)