In html, a form with multipart data:
<form action="@routes.Files.upload" method="post" enctype="multipart/form-data"> <input type="hidden" name="groupId" value="1" /> <input type="hidden" name="tagId" value="2" /> <input type="file" name="file"/> <input type="submit" value="upload it"/> </form>
How to write the action Files upload
?
I know how to get a uploaded file:
request.body.file("file") map { filepart => filepart.ref.moveTo(newFile); }
And how to get submitted inputs:
Form(tuple("groupId" -> text, "tagId" -> text)).bindFromRequest.fold( errors => ..., params => .... )
But how to combine them together?
I don't find a suitable type for file
can be used in Form(tuple(...))
, and neither a way to get input value in request.body
.
Multipart upload allows you to upload a single object as a set of parts. Each part is a contiguous portion of the object's data. You can upload these object parts independently and in any order. If transmission of any part fails, you can retransmit that part without affecting other parts.
Follow this rules when creating a multipart form: Specify enctype="multipart/form-data" attribute on a form tag. Add a name attribute to a single input type="file" tag. DO NOT add a name attribute to any other input, select or textarea tags.
getElementById('#uploadID'); el. onchange = function(){ // your code... }; However, javascript validation is good idea but make sure that you do the actual validation on the server-side :) Should be 'uploadID' instead of '#uploadID'.
This answer is for Java, but you should be able to adapt it to Scala fairly easily.
What you need to do is define a Model for all the fields in your form except the file. Then use the file-upload API as normal to retrieve the file.
For example, this is what I did:
The Form (in upload.scala.html):
@form(action = routes.UploadResourceController.doUpload(), 'enctype -> "multipart/form-data") { @inputText(uploadForm("lang")) @inputText(uploadForm("country")) @inputFile(uploadForm("resourceFile")) <p> <input type="submit"> </p> }
The Model (models/UploadResource.java):
public class UploadResource { @Required public String lang; @Required public String country; /* notice a field for the file is missing */ }
The Controller (controllers/UploadResourceController.java):
public static Result doUpload() { Form<UploadResource> filledForm = uploadForm.bindFromRequest(); if (filledForm.hasErrors()) { return badRequest(views.html.upload.render(filledForm)); } else { UploadResource resource = filledForm.get(); MultipartFormData body = request().body().asMultipartFormData(); FilePart resourceFile = body.getFile("resourceFile"); /* Check resourceFile for null, then extract the File object and process it */ } }
I hope this helps.
An example in Scala where the form field is required:
Model:
case class Specs (userid: String)
Controller:
object Upload extends Controller { val uploadForm = Form( mapping( "userid" -> nonEmptyText )(Specs.apply)(Specs.unapply) ) def upload = Action(parse.multipartFormData) { implicit request => val sp : Option[Specs] = uploadForm.bindFromRequest().fold ( errFrm => None, spec => Some(spec) ) request.body.file("file").map { f => sp.map { spec => val filePath = ... // incorporate userid // XXX: file read to memory b4 writing to disk. bad for large files f.ref.moveTo(new File(filePath), replace=true) Ok("File uploaded") }.getOrElse{ BadRequest("Form binding error.") } }.getOrElse { BadRequest("File not attached.") } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With