Introduction
Hello Ninjas!! Welcome to another article on Scala. Today we will learn about Handling file upload. Scala is an object-oriented programming language that supports the functional programming approach. Scala allows us to create, upload, read, and write files. There are different methods to upload files. We will look into the details of each of them.
Without further ado, let's get started.
Methods of File upload
You can upload files in Scala using the following ways:

-
Uploading the Files in a Form Using multipart/form-data
-
Direct file upload
-
Writing your body-parser
Let's get into the details of handling file upload of each of them.
Uploading the Files in a Form Using multipart/form-data.
It is the usual way to upload files in a web application. It uses a form with special multipart/form-data encoding.
Let's see How to create an HTML form:
<html>
<head>
<Title>Scala File Upload</Title>
</head>
<body>
<center>
<H1> Welcome to Scala- Handling File upload</H1>
<form action=routes.HomeController.fileupload enctype="multipart/form-data">
<p>File to upload: <input type="file" name="document" /></p>
<p><input type="submit" value="Upload" /></p>
</form>
</center>
</body>
</html>
Output:

Put the CSRF token (Secure Token) before the file input field. The CSRF filter checks the multipart form in the order in which the areas are listed.
Let's see how you can define the upload action using a multipartFormData body parser.
Code:
def fileupload = Action(parse.multipartFormData) { request =>
request.body
.file("CodingNinjas")
.map { document =>
// get the filename only up to the last section
val fname = Paths.get(document.filename).getFileName
val fSize = document.fileSize
val ctype = document.contentType
CodingNinjas.ref.copyTo(Paths.get(s"/coding/ninjas/$filename"), replace = true) //Specify the File name with location
Ok("Successfully uploaded the file")
}
.getOrElse {
Redirect(routes.HomeController.index).flashing("error" -> "File not found")
}
}
The above code ensures that whenever an empty or wrong file location is given as input. It will display the output as:
Output:

Now add a POST router.
POST / democontrollers.HomeController.upload()
The behavior of an empty file will be the same as a file never exist.
You can construct an error handler to deal with the situation where a user uploads a file that is too big:
error {
case e: SizeConstraintExceededException => RequestEntityTooLarge("File Size is Large!!")
}
Whenever you try to upload a large size file, you will get the output as:
Output:

Direct file upload
It is another way to send files to the server. It uses Ajax to upload files from a form asynchronously.
In the previous method, we have used multipart/form-data encoding. In this method, the request body will not be encoded as the multipart/form-data. It contains only the plain text file.

Let's utilize the TemporaryFile body parser for this illustration:
def upload = Action(parse.temporaryFile) { request =>
request.body.moveTo(Paths.get("/coding/ninjas/filename"), replace = true) //Specify the file name with location
Ok("Successfully uploaded the file")
}
Output:

Writing your body-parser
We use the Temporary File body parser in the above method to handle the file uploads. You can make your body parser if you want to handle the file upload directly without buffering it in a temporary file. But in this case, you will receive chunks of data that you are free to push anywhere you want.
You may still use the default multipartFormData parser if you want to utilize multipart/form-data encoding. This can be done by giving a FilePartHandler[A] and a separate Sink. The sink is used to gather data. You can specify an Accumulator(fileSink) and you can use a FilePartHandler[File] instead of a TemporaryFile.
Code:
type FilePartHandler[A] = FileInfo => Accumulator[ByteString, FilePart[A]]
def handlerA: FilePartHandler[File] = {
case FileInfo(partName, filename, contentType, dispositionType) =>
val permission = java.util.EnumSet.of(OWNER_READ, OWNER_WRITE)
val attributes = PosixFilePermissions.asFileAttribute(permission)
val path = JFiles.createTempFile("multipartBody", "tempFile", attributes)
val file = path.toFile
val fSink = FileIO.toPath(path)
val accum = Accumulator(fSink)
accumulator.map {
case IOResult(count, status) =>
FilePart(partName, filename, contentType, file, count, dispositionType)
}(ec)
}
def customUpload = Action(parse.multipartFormData(handlerA)) {
filename =>val options= request.body.file("CodingNinjas.txt").map {
case FilePart(key, filename, contentType, file, fileSize, dispositionType) =>
file.toPath
}
Ok(s"Successfully uploaded the file: $filename")
}
In the above code snippet, we have uploaded the file CodingNinjas.txt. The output will be displayed as:
Output:
