forms - ¿Cómo obtener el archivo de carga con otras entradas en play2?
file-upload playframework-2.0 (4)
En html, un formulario con datos multiparte:
<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>
Cómo escribir la acción ¿ Files upload
?
Sé cómo obtener un archivo cargado:
request.body.file("file") map {
filepart => filepart.ref.moveTo(newFile);
}
Y cómo obtener entradas enviadas:
Form(tuple("groupId" -> text, "tagId" -> text)).bindFromRequest.fold(
errors => ...,
params => ....
)
Pero, ¿cómo combinarlos juntos?
No encuentro un tipo adecuado para el file
se pueda usar en Form(tuple(...))
, ni una forma de obtener valor de entrada en request.body
.
Esta respuesta es para Java, pero debería poder adaptarla a Scala con bastante facilidad.
Lo que necesita hacer es definir un Modelo para todos los campos en su formulario excepto el archivo. Luego use la API de carga de archivos como es normal para recuperar el archivo.
Por ejemplo, esto es lo que hice:
El formulario (en 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>
}
El modelo (modelos / UploadResource.java):
public class UploadResource {
@Required
public String lang;
@Required
public String country;
/* notice a field for the file is missing */
}
El controlador (controladores / 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 */
}
}
Espero que esto ayude.
Estaba cargando un archivo usando angular, con otros parámetros de formulario. Creé el mío como a continuación y funciona.
Función angular
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);
});
Play 2.1 Controlador
/**
*
*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");
}
}
Otro ejemplo de cómo hacer esto puede ser este:
Modelo:
case class Specs(userId: String)
Controlador
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)
}
}
)
No olvides nombrar el archivo, porque podrías terminar preguntándote qué salió mal.
Un ejemplo en Scala donde se requiere el campo de formulario:
Modelo:
case class Specs (userid: String)
Controlador:
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.")
}
}
}