Creating a file upload system with play 2.6.x(Scala) part 1: Multipart/form-data

in #utopian-io7 years ago

Screenshot (67).png

Repository

https://github.com/playframework/playframework

What Will I Learn?

In this tutorial you will learn the following

  • Defining form actions in views
  • setting form multipart/form-data enctype
  • setting POST and GET Methods for file upload forms in routes
  • Rendering an upload form using controller actions
  • File upload using multipart/form-data encoding

Requirements

The following are required in order to properly follow along this tutorial.

  • Intellij IDEA
  • sbt
  • playframework with slick installed
  • Web browser
  • Basic knowledge of Scala programming language

Resources

Difficulty

  • Intermediate

Tutorial Contents

Welcome to today's tutorial on how to build a file upload system using Multipart/form-data in the play(scala) framework. This tutorial is part of a series of tutorials that I hope to present and each one in the series promises to be exciting.

Before we begin I will like to define a basic concept which we need to know in order to properly understand basic file upload.

Multipart/form-data

The Multipart/form-data is an a file encoding type that allows files to be sent using a post request. Which means that for files to be sent through post they must first be encoded using this enctype or encoding type.

This is a standard way of uploading files in a web application as it allows you to mix standard form data with file attachment.

Defining the upload form

before a form is displayed you might sometimes need to create a case class for that form, then define the form by setting it to the apply and unapply methods of the case class. Please note that the case class can be defined out in a separate file which can be referenced, or outside the main class definition in a separate block. source code below

val form = Form(
    mapping(
      "name" -> text
    )(UploadForm.apply)(UploadForm.unapply)
  )

Code Explanation

  1. In defining our form we first declare a variable known which we will call form

  2. The next thing we do is to call the form function which takes in a mapping as a parameter

  3. inside the mapping we declare a form data known as name and has a type of text, in other cases it can be filename, email, or whatever you want it to be

  4. lastly we then set it to the UploadForm apply and unapply methods.

After declaring the upload form, we need to create a form action to render the form render the form, we will the define a function called uploader that would handle file upload requests.

  def uploader = Action(parse.multipartFormData) { implicit request =>
    request.body.file("file").map { picture =>
      picture.ref.moveTo(Paths.get(s"/Users/Alexis/Downloads/"+picture.filename).toFile, replace = true)
      Ok("File upload successful")
    }.getOrElse {
      Redirect(routes.FileUploadController.index).flashing(
        "error" -> "File not found")
    }
  }

Code Explanation

  1. We use the picture.ref.moveTo function to set the destination of the file, the Paths.get function retrieves the file name which is then appended to the correct storage location in our case the file will be uploaded to Users/Alexis/Downloads

  2. The toFile function converts it from a path to file file for upload, while the replace = true statement overwrites any previous existing file of the same file name

  3. We then display an ok that says file upload successful, when the file has been successfully uploaded

  4. To create an alternate condition that is activated when there is an error uploading the file we call the getOrElse Condition which the redirects to the index page

  5. The Redirect() function redirects to routes.FileUploadController.index which is the default route for our application or our application's home page

  6. After the we display a flashing error message to the user that says file not found

Setting the form multipart/form-data enctype

In the views is where we define the form template, this is where we will set the enctype to multipart/form-data. for a better understanding of this you are advised to read on upload forms using HTML, that might give you a basic understanding of this concept.

@(form: Form[controllers.UploadForm])

@main("Welcome to Play") {
    @helper.form(action = routes.FileUploadController.uploader, 'enctype -> "multipart/form-data") {
        @helper.inputFile(form("file"))
        <input type="submit" value="upload"/>
    }
}

Code Explanation

  1. In displaying our form, we begin by setting the form action to routes.FileUploadController.uploader, which is the routes that processes the upload request. The uploader function has already been defined in our controller.

  2. We define a helper for a form input type, which is giving the name, file. The @helper.inputFile is the same as the form input type selection.

  3. Finally our submit button is defined using HTML syntax, and the value of the button is set to upload

Setting POST and GET methods in our routes

Our application cannot be complete without setting both POST and GET methods for our application. Like I said earlier multipart/form-data sends files using POST requests, so it's very important you set this. To set the POST and GET variables we do the following.

GET    /fileupload                  controllers.FileUploadController.index

POST   /uploadpage                  controllers.FileUploadController.uploader

Code Explanation

  1. We set a GET variable which has a URL called /fileupload and it maps to controllers.FileUploadController.index. By defualt the index page displays only the form.

  2. we set a POST variable known as /uploadpage, this is the action that will be activated when the user clicks the upload button. It activates the uploader function in the FileUploadController

To test our application, go to localhost:9000/fileupload. Screenshot below

Screenshot (92).png

Proof of Work Done

Proof of work done can be found here
https://github.com/leczy642/leczy642-play-scala-file-upload

Curriculum

Sort:  
  • There is a tutorial similar to yours. link

Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]