2012-02-26 5 views
23

in HTML, un modulo con i dati multipart:Come ottenere il file di caricamento con altri input in play2?

<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> 

Come scrivere l'azione Files upload?

so come ottenere un file caricato:

request.body.file("file") map { 
    filepart => filepart.ref.moveTo(newFile); 
} 

e come input per essere presentate:

Form(tuple("groupId" -> text, "tagId" -> text)).bindFromRequest.fold(
    errors => ..., 
    params => .... 
) 

Ma come combinarli insieme?

Non trovo un tipo adatto per file può essere utilizzato in Form(tuple(...)) e né un modo per ottenere il valore di input in request.body.

risposta

25

Questa risposta è per Java, ma dovresti essere in grado di adattarlo a Scala abbastanza facilmente.

Quello che dovete fare è definire un modello per tutti i campi nel modulo eccetto il il file. Quindi utilizzare l'API di caricamento file come di consueto per recuperare il file.

Ad esempio, questo è quello che ho fatto:

Il modulo (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> 
} 

Il Modello (modelli/UploadResource.java):

public class UploadResource { 
    @Required 
    public String lang; 

    @Required 
    public String country; 

    /* notice a field for the file is missing */ 
} 

Il controller (controller/UploadResource Controller.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 */ 
    } 
} 

Spero che questo aiuti.

+0

Che cosa succede se si desidera memorizzare la posizione del file nel modello? Altrimenti, come saprai dove si trova il file dopo averlo elaborato? Immagino che mi manchi quello che è la "API di caricamento file": http://commons.apache.org/proper/commons-fileupload/using.html? –

+0

@SkylarSaveland: questo codice consente solo di ottenere i dati del modulo e il file. Una volta ottenuto il file (il file di risorse nel mio esempio), puoi spostarlo ovunque desideri archiviarlo e aggiornare il tuo modello con la posizione e il nome file. – JBCP

13

Un esempio a Scala, dove è necessario il campo modulo:

Modello:

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.") 
     } 
    } 
} 
3

Un altro esempio come fare questo può essere questo :

Modello:

case class Specs(userId: String) 

controller

def upload = Action(parse.multipartFormData) { implicit request => 
    uploadForm.bindFromRequest().fold(
    hasErrors => Ok(ourFormHTML(hasErrors), 
    specs => { 
     request.body.file("inputFileFieldName") match { 
     case Some(file) => { 
      import java.io.File 
      val filename = file.filename 
      val contetType = file.contentType 
      file.ref.moveTo(new File(Play.application().path().getAbsolutePath + file.filename)) 
      Ok("congratz you did it") 
     } 
     case _ => Ok(ourHTML if we dont send file but want the form anyway) 
     } 
    } 


) 

Non dimenticate il nome del file, perché si potrebbe finire per chiedersi cosa è andato storto.

2

Stavo caricando un file usando angolare, con altri parametri del modulo. Ho creato il mio come sotto e funziona.

angolare Funzione

Upload.upload({ 
    url: '/api/upload', 
    method:'POST', 
    data: { 
     "file": user.profilePic, //file object 
     "username": user.username 

    } 
}).then(function (resp) { 
    //console.log('Success ' + resp.config.data.file.name + 'uploaded. Response: ' + resp.data); 

}, function (resp) { 
    console.log('Error status: ' + resp.status); 
}, function (evt) { 
    var progressPercentage = parseInt(100.0 * evt.loaded/evt.total); 
    //console.log('progress: ' + progressPercentage + '% ' + evt.config.data.file.name); 
}); 

Gioca 2.1 controller

/** 
* 
*Upload user profile 
**/ 
public static Result upload() { 
    Logger.info("Uploading images##"); 
    Http.MultipartFormData body = request().body().asMultipartFormData(); 
    Http.MultipartFormData.FilePart profile = body.getFile("file"); 
    if (profile != null) { 
     File file = profile.getFile(); 

     //upload file to a directory 
     //todo 

     //get the username from form 
      Map<String,String[]> dataPart = request().body().asMultipartFormData().asFormUrlEncoded(); 
      String username = dataPart.get("username")[0]; 

      //save/update the details with ebean 

     return ok("File uploaded"); 
    } else { 

     return status(400, "Missing file"); 
    } 
} 
Problemi correlati