Last Updated: February 25, 2016
·
2.277K
· ignasi35

Play! 2.1+ FileUpload without Temp files

When uploading a file in Play! 2.1+ the suggested method (and default implementation) cause the file content to be dumped into a temp file.

(see http://www.playframework.com/documentation/2.1.1/ScalaFileUpload)

On top of that, the API allows you to obtain the content of the File by copying the temp File to a File under your control:

picture.ref.moveTo(new File("/tmp/picture"))

Mem-only implementation

It is possible to create a mem-only implementation (it has a drawback, you may OOME!).

Step 1

Have your action know the multipart handling by stating it:

def doUpload = Action(multipartFormData(myHandleFilePart)) {
  request => [...]

Step 2

Create a FilePart Handler to return the type you desire (in my case Array[Byte]):

private def myHandleFilePart: PartHandler[FilePart[Array[Byte]]] = {
  handleFilePart {
    case FileInfo(partName, filename, contentType) =>
      val baos = new java.io.ByteArrayOutputStream()
      Iteratee.fold[Array[Byte], java.io.ByteArrayOutputStream](baos) {
        (os, data) =>
          os.write(data)
          os
      }.mapDone {
        os =>
          os.close()
          baos.toByteArray
      }
  }
}

Step 3

Review your file consumiption since the request will now return a FilePart that contains an Array[Byte] ref:

def doUpload = Action(multipartFormData(myHandleFilePart)) {
  request =>
    request.body.file("fileUpload").map {
      file =>
        val bytes: Array[Byte] = file.ref
        [...]

Enjoy!

PS: You could also pass the byte chunks as they arrive by piping the receiveing iteratee with the next step of you file management, but that's out of the scope of this snippet.