How will 100 simultaneous slow download requests (number of threads) be handled?
It depends. The number of actual threads used is not significant. By default, Play uses the number of threads equal to the number of processor cores available. But this does not mean that if you have 4 cores, you are immediately limited to four simultaneous processes. Play HTTP requests are processed asynchronously in a special internal ExecutionContext provided by Akka. Processes running in an ExecutionContext can share threads if they are not blocked, which abstracts from Akka. All this can be configured in different ways. See Understanding Playback Stream Pools .
Iteratee , which consumes client data, must do some locking in order to write file fragments to disk, but performed in small (and fast) sufficient fragments, this should not lead to blocking the download of other files.
What bothers me more is the amount of disk I / O that your server can handle. 100 slow downloads might be fine, but you can't tell without benchmarking. At some point, you will have problems when client input exceeds the speed that your server can write to disk. It will also not work in a distributed environment. I almost always prefer to completely bypass the Play server and directly upload it to Amazon S3.
Will a file be buffered in memory or transferred directly to disk?
All temporary files are transferred to disk. Under the hood, all data sent from the client to the server is read asynchronously using the iteratee library. For multi-page downloads, this is no different. Client data is consumed using Iteratee , which transfers file fragments to a temporary file on disk. Therefore, when using parse.temporaryFile BodyParser , request.body is just a temporary file descriptor on disk, not a file stored in memory.
It is worth noting that, although Play can handle these requests in a non-blocking manner, the file will be blocked after completion. That is, request.body.moveTo(...) blocks the function of the controller until the move is complete. This means that if several of the 100 downloads are completed at approximately the same time, the Play internal ExecutionContext for query processing can quickly reboot. The core moveTo API is also deprecated in Play 2.3, as it uses FileInputStream and FileOutputStream to copy the TemporaryFile to a permanent location. The docs advise you to use the Java 7 file APIs instead, as it is much more efficient.
It might be a little rude, but something like this should do it:
import java.io.File import java.nio.file.Files def upload = Action(parse.temporaryFile) { request => Files.copy(request.body.file.toPath, new File("/tmp/picture/uploaded").toPath) Ok("File uploaded") }