Table of contents
1.
Introduction
2.
Methods of File upload
2.1.
Uploading the Files in a Form Using multipart/form-data.
2.2.
Direct file upload
2.3.
Writing your body-parser
3.
Cleaning up temporary files
4.
Frequently Asked Questions
4.1.
What is Scala?
4.2.
Is it possible to upload a file without buffering it in a temporary file?
4.3.
What is a body parser?
4.4.
Why is it necessary to clean temporary files?
5.
Conclusion
Last Updated: Mar 27, 2024
Medium

Scala developers-Handling File upload

Author Nagendra
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

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.

Scala Developers

Without further ado, let's get started.

Methods of File upload

You can upload files in Scala using the following ways:

Scala Handling File Upload Image
  • 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:

Html form image

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:

File Not Found exception image

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:

File Size is large exception image

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.

Scala file upload Image

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:

Uploading file message image.

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:

Uploading file message image.

Cleaning up temporary files

Uploading files is an inherently risky process because an unbounded file upload can fill the storage of file system. 

Temporary files Image

Therefore, we use TemporaryFile. This ensures that the temporary file is removed out of the temporary file system as soon as possible. Also, any temporary files that are not moved are deleted. TemporaryFileReaper can be configured to destroy temporary files on a predetermined timetable using the scheduler.

By default, the reaper is turned off and is enabled by setting up the application.conf:

Code:

play.temporaryFile {
	reaper {
	enabled = true
	initDelay = "6 minutes"
	gap = "30 seconds"
	lifespan = "40 minutes"
	}
}


Using the "lifespan" attribute, the configuration above will delete files older than 40 minutes. Six minutes after the application launches, the reaper will begin, and it will inspect the filesystem over the next 30 seconds.

Check out this article - File System Vs DBMS

Frequently Asked Questions

What is Scala?

Scala is an object-oriented programming language that allows the functional programming approach also. Scala applications can be translated into bytecodes and run on the JVM (Java Virtual Machine). 

Is it possible to upload a file without buffering it in a temporary file?

Scala file handling techniques allow you to write your BodyParser if you want to handle file uploads directly rather than buffering them in temporary files. In this scenario, you will be given data chunks that you are free to push wherever you like.

What is a body parser?

An HTTP PUT or POST request contains a body. This body can use any format specified in the Content-Type request header. In Scala, a body parser transforms this request body into a Scala value.

Why is it necessary to clean temporary files?

The idea behind TemporaryFile is that it should be removed from the temporary file system as soon as it is finished since it is only in scope at completion. If not cleaned, temporary files can occupy unnecessary space and reduce the system's performance.

Conclusion

In this article, we have extensively discussed the details of Handling File upload in Scala and different ways of uploading files in Scala applications.
We hope that the blog has helped you enhance your knowledge regarding Handling File upload in Scala. You can refer to our guided paths on the Coding Ninjas Studio platform to learn more about DSADBMSCompetitive ProgrammingPythonJavaJavaScript, etc. To practice and improve yourself in the interview, you can also check out Top 100 SQL problemsInterview experienceCoding interview questions, and the Ultimate guide path for interviews. Do upvote our blogs to help other ninjas grow. Happy Coding!!

Live masterclass