Filebodyparser,在play2中输入文本字段

时间:2015-02-10 10:41:31

标签: forms file-upload playframework-2.3 iterate

我正在使用Bootstrap tagsinput使用标签注释我的文件:

@helper.form(action=routes.Upload.save(projectId), 'enctype -> "multipart/form-data" ) 
{   
    <input type="file" name="corpus">   
    <input type="text" value="Amsterdam,Washington,Sydney,Beijing,Cairo"  name="tags" id="tags" data-role="tagsinput"/>
    <input type="submit">
}

在控制器中,我试图将请求绑定到表单:

  def save(id:Long) = Action(requestCsvBodyParser){ implicit request =>
    uploadForm.bindFromRequest.fold(
      hasErrors => {
        BadRequest
      },
      success = { formData =>
        // accessing formData.tags
        // parsing request.body and store in the database with tags
        Ok("Got request")
      }
    )
  }

requestCsvBodyParser是Iteratee [Array [Byte],List [String]]。据我所知,该文件不应该是验证表单的一部分,所以我将表单定义如下:

  private val uploadForm = Form(
    mapping(
      "tags" -> list(text)
    )(UploadTags.apply)(UploadTags.unapply)
  )

会导致请求成功,但空tags。如果我使用text代替list(text),那么我总是以BadRequest结尾。

当我在表单验证中执行此操作时,如果它是解析的反应方式,我也不会感到害羞。

编辑(添加Bodyparser) BodyParser:

 /** Enumeratee that transforms a stream of Array[Byte] into a stream of Byte */
  val toBytes: Enumeratee[Array[Byte], Byte] = Enumeratee.mapInputFlatten[Array[Byte]] {
    case Input.El(arr) => Enumerator[Byte](arr: _*)
    case Input.Empty => Enumerator.empty[Byte]
    case Input.EOF => Enumerator.eof[Byte]
  }

  val concatLine: Iteratee[Parsing.MatchInfo[Array[Byte]],String] =
    ( Enumeratee.breakE[Parsing.MatchInfo[Array[Byte]]](_.isMatch) ><>
      Enumeratee.collect{
        case Parsing.Unmatched(bytes) => new String(bytes)
      } &>>
      Iteratee.consume() ).flatMap(r => Iteratee.head.map(_ => r))

  val txtToParagraph: Iteratee[Array[Byte], List[String]] =
    Parsing.search("\r\n\r\n".getBytes) ><>
      Enumeratee.grouped( concatLine ) &>>
      Iteratee.head.flatMap( header => Iteratee.getChunks.map(header.toList ++ _) )


  val requestCsvBodyParser = BodyParser(rh => txtToParagraph.map(Right(_)))

1 个答案:

答案 0 :(得分:1)

如果您希望将表单值解析为列表,则需要在输入名称中添加索引,例如:tags[0]tags[1],或者只是按照概述附加[]2.4.x form docs section on repeated values

另一方面,如果您希望单个文本字段接受以逗号分隔的值作为列表结束,那么您可以像这样对它们进行转换:

import play.api.data.Form
import play.api.data.Forms._

case class UploadTags(
  tags: List[String]                  
)

object UploadTags {
  val form = Form(
    mapping(
      "tags" -> text.transform[List[String]](
        str => str.split(",").map(_.trim).toList,
        list => list.mkString(",")
      )
    )(UploadTags.apply)(UploadTags.unapply)
  )
}

即。提供一个函数来将值打包并解压缩到单个表单字段中。

纠正文件上传应该/可以单独验证。