如何在play2中获取带有其他输入的上传文件?

Posted

技术标签:

【中文标题】如何在play2中获取带有其他输入的上传文件?【英文标题】:How to get the upload file with other inputs in play2? 【发布时间】:2012-03-16 04:18:40 【问题描述】:

html中,多部分数据的表单:

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

动作Files upload怎么写?

我知道如何获取上传的文件:

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

以及如何获取提交的输入:

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

但是如何将它们组合在一起呢?

我没有找到适合file 的类型可以在Form(tuple(...)) 中使用,也没有在request.body 中获取输入值的方法。

【问题讨论】:

【参考方案1】:

此答案适用于 Java,但您应该能够相当轻松地将其适应 Scala。

您需要做的是为表单中的所有字段定义一个模型除了文件。然后像往常一样使用文件上传 API 来检索文件。

例如,这就是我所做的:

表单(在 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>

模型 (models/UploadResource.java):

public class UploadResource 
    @Required
    public String lang;

    @Required
    public String country;

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

控制器(控制器/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 */
     

我希望这会有所帮助。

【讨论】:

如果要在模型中存储文件的位置怎么办?否则,处理完文件后如何知道文件的位置?我想我错过了“文件上传 API”是什么 - commons.apache.org/proper/commons-fileupload/using.html ? @SkylarSaveland - 此代码仅允许您获取表单数据和文件。获得文件(在我的示例中为 resourceFile)后,您可以将其移动到要存储它的任何位置,并使用位置和文件名更新您的模型。【参考方案2】:

Scala 中需要表单字段的示例:

型号:

case class Specs (userid: String)

控制器:

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

如何做到这一点的另一个例子是:

型号:

case class Specs(userId: String)

控制器

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)
      
   


 )

不要忘记为文件命名,因为您最终可能会想知道出了什么问题。

【讨论】:

【参考方案4】:

我正在使用 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);
);

播放 2.1 控制器

/**
*
*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");
    

【讨论】:

以上是关于如何在play2中获取带有其他输入的上传文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 SSIS 的 FTP 上传文件

如何从用户定义的输入中上传图像以做出反应?

玩 2.4:如何使用 MultipartFormData 编写文件上传测试用例

使用带有 Ionic 的文件输入的文件上传(使用本机文件浏览器选择文件)

如何将上传图标修复为文件上传输入(材料 UI)

如何以小块上传带有ajax的文件并检查失败,重新上传失败的部分。