Akka HTTP / How to change the pathPrefix/file name for an OutputStream?

The user sends a post request, than based on that post body I create an Excel file (.xlsx) and want to send that file back, without storage of that file itself.

def writeAsync(out: OutputStream): Unit = {
  Future {
    val wb = new XSSFWorkbook
    val sheet1: Sheet = wb.createSheet("sheet1");
    val os = new ByteArrayOutputStream()
    wb.write(os)
    os.writeTo(out)
    out.close()
    wb.close()
  }
}

...

pathPrefix("createAndDownloadExcel") {
  post {
    ...
    val generatedFileName = "customGeneratedFileName.xlsx" // <-- this name should the file name be like
    val (out, source) = StreamConverters.asOutputStream().preMaterialize()
    writeAsync(out)
    complete(HttpEntity(ContentTypes.`application/octet-stream`, source))
  }
}

The response has the excel content with the file name: "createAndDownloadExcel", but I would like it to have the file name based on the individual generated file name.

The name will be later manually generated based on the POST body, whereby a simple change in pathPrefix("fixedName.xlsx") does not work for my needs.

How can I solve this, being able to give a dynamic file name for that returned OutputStream?


"org.apache.poi" % "poi-ooxml" % "5.2.0" 

Solution 1:

Try adding response header Content-Disposition.

The first parameter in the HTTP context is either inline (default value, indicating it can be displayed inside the Web page, or as the Web page) or attachment (indicating it should be downloaded; most browsers presenting a 'Save as' dialog, prefilled with the value of the filename parameters if present).

import akka.http.scaladsl.model.headers.ContentDispositionTypes.attachment
import akka.http.scaladsl.model.headers.`Content-Disposition`
....

respondWithHeader(`Content-Disposition`(attachment, Map("filename" -> "customGeneratedFileName.xlsx"))) {
  complete(HttpEntity(ContentTypes.`application/octet-stream`, source))
}