How to convert an OutputStream created by OpenPdf (java library) to readable and downloadable via http response (http4s, scala) pdf document?

158 views Asked by At

I want my http-service (Scala, http4s, Ember) to receive a http-request, create a pdf document using OpenPdf library and make a http-response to user's browser with this pdf document. User should see pdf inside the browser or download it.

I have a route for GET request:

case GET -> Root / "pdf" / IntVar(book) => getBookF(book) match {

        case Some(bookF: BookF) =>
          val b = createPdfSingleBook(bookF)
          Ok(b, Header.Raw(CIString("Expires"), "0"),
            Header.Raw(CIString("Cache-Control"), "must-revalidate, post-check=0, pre-check=0"),
            Header.Raw(CIString("Pragma"), "public"), Header.Raw(CIString("Content-Length"), s"${b.length}"),
            Header.Raw(CIString("Content-Type"), "application/pdf"))

        case None => NotFound()
def createPdfSingleBook(bookF: BookF): String = {

    val monolingualBook = new Document()

    val pdfOutputFile: FileOutputStream = new FileOutputStream(s"${book.id}.pdf")
    val baos: ByteArrayOutputStream = new ByteArrayOutputStream()

    val baosWriter = PdfWriter.getInstance(monolingualBook, baos)
    val pdfWriter: PdfWriter = PdfWriter.getInstance(monolingualBook, pdfOutputFile)

    monolingualBook.open()

    //Content of a pdf-document

    val res = Base64.getEncoder.encodeToString(baos.toByteArray)

    monolingualBook.close()
    baosWriter.close()
    pdfWriter.close()

    res
  }

There are two OutputStreams in the code. FileOutputStream works and I have a pdf document saved on my disk. I want the same result in the browser: same document opened in the browser. Please, help!

1

There are 1 answers

5
Philluminati On

Have your PDF book return the raw Array[Byte] rather than a String:

def createPdfSingleBook(bookF: BookF): Array[Byte] = {

    val monolingualBook = new Document()

    val baos: ByteArrayOutputStream = new ByteArrayOutputStream()
    val baosWriter = PdfWriter.getInstance(monolingualBook, baos)

    monolingualBook.open()

    //Content of a pdf-document
    // Use baosWriter here....

    monolingualBook.close()
    baosWriter.close()

    baos.toByteArray
  }

Return 200 OK with the body being the pdf and the content-type set:

val pdfData :Array[Byte] = createPdfSingleBook(...)

Ok(pdfData, Header("Content-type", "application/pdf"))