-->

how to handle fileupload into a table in play fram

2020-07-31 19:48发布

问题:

i have a table called system it has some columns mainly number / char types but there is one binary type for holding a document (word or excel etc)

ignore for now if we should hold the file inline or external i.e. bfile or blob... the question is more about how to handle it in the play framework

I have got the form working with the model view and controller... but i set it up without the file-field just to get it working:

I have a case class in the model

case class System(sys_id: Pk[Long] = NotAssigned 
  , sys_name: String 
  , sys_desc: String 
  , sys_owner1: Long 
  , sys_owner2: Long) 

a form in the controller

val systemForm = Form(
    mapping(
      "sys_id" -> ignored(NotAssigned:Pk[Long]),
      "sys_name" -> nonEmptyText,
      "sys_desc" -> nonEmptyText,
      "sys_owner1" -> longNumber,
      "sys_owner2" -> longNumber
    )(System.apply)(System.unapply)
  )

and a form in the view

@form(routes.Systems.save(), 'class -> "form-horizontal") {  
            @inputText(systemForm("sys_name"), '_label -> "System Name")
            @inputText(systemForm("sys_desc"), '_label -> "Description")
            @select(
                systemForm("sys_owner1"), 
                persons, 
                '_label -> "Primary Owner", '_default -> "-- Choose a person --",
                '_showConstraints -> false
            )
            @select(
                systemForm("sys_owner2"), 
                persons, 
                '_label -> "Secondary Owner", '_default -> "-- Choose a person --",
                '_showConstraints -> false
            )
            <div class="control-group">
              <div class="controls">
                 <input type="submit" value="Create System" class="btn btn-success"> or 
                 <a href="@routes.Systems.list()" class="btn">Cancel</a> 
              </div>
            </div>
    }

This all works well... but now i want to add the file in, what should i do? I have seen this http://www.playframework.com/documentation/2.1.2/ScalaFileUpload but it confuses me it makes no mention of if or how i should change the case class - and what variable is the file stored in (if it is) so that I can access it in my code?

should I modify my case class (if so what type should i add)? should I modify the Form in the controller (again if so what type should I add?)

im not bothered whether I store it inline or as a bfile - but how can I handle it as asked above?

Thank you

回答1:

There are some items to consider:

  1. In your .scala.html file, you'll need a file upload field <input type="file" name="someName">.

  2. You'll need to set the encoding type of the form as stated in the documentation: 'enctype -> "multipart/form-data".

  3. You can then change your controller to to handle multipart form-data, so it looks like the one in the example. Use Action(parse.multipartFormData) to parse the form. I think you should then also be able to use your form with systemForm.bindFromRequest (from Form API), although I haven't tried that before.

Edit:

What I meant was to treat the uploaded file and the rest of the form data as separate items.

Try changing the example form the documentation to look like this:

def upload = Action(parse.multipartFormData) { request =>
  request.body.file("picture").map { picture =>
    import java.io.File
    val filename = picture.filename 
    val contentType = picture.contentType
    picture.ref.moveTo(new File("/tmp/picture"))

    // this is the new part
    val formContents = systemForm.bindFromRequest.value
    // now you can do stuff with `formContents` and `picture`

    Ok("File uploaded")
  }.getOrElse {
    Redirect(routes.Application.index).flashing(
      "error" -> "Missing file"
    )
  }

}