3

我想知道如何使用http4s库处理多部分内容。

想象一个具有以下片段的服务(完整的要点在这里):

  case GET -> Root / "form" =>
   Ok(
   """|<html>
      |<body>
      |<form method="post" action="/post" enctype="multipart/form-data">
      | <input type="date" name="birthDate" placeholder="birthDate">
      | <input type="file" name="dataFile">
      | <input type="submit">
      |</form></body></html>""".stripMargin).
      withContentType(Some(`Content-Type`(`text/html`)))

case req @ POST -> Root / "post" => {
 req.decode[Multipart[IO]] { m =>
  Ok(
    s"""Multipart Data\nParts:${m.parts.length}
       |${m.parts.map { case f: Part[IO] => { f.name + ", headers: " + f.headers.mkString(",")} }.mkString("\n")}""".stripMargin)
}
  }

如果我执行服务并填写相应的字段,我将获得如下输出:

Multipart Data
Parts:2
Some(birthDate), headers: Content-Disposition: form-data; name="birthDate"
Some(dataFile), headers: Content-Disposition: form-data; name="dataFile"; 
 filename="file.pdf",Content-Type: application/pdf

所以我知道如何获取有关部件的信息,这些部件是 typePart[IO]和 contains headersand的元素body

我想知道如何处理这些部分。例如,在这种情况下,我想打开文件并告知其长度。这样做的惯用方法是什么?

4

1 回答 1

3

bodyofPart[IO]Stream[F[_],Byte]可以使用库中的方法处理的fs2

io.file.writeAll有几种可能性,一种可能性是使用andio.file.writeAllASync方法将流内容写入文件。

另一种适用于基于字符串的文件的可能性是使用该utf8Decode方法处理流的内容。

结果可能是:

  case req @ POST -> Root / "post" => {
    req.decode[Multipart[IO]] { m => {
      m.parts.find(_.name == Some("dataFile")) match {
        case None => BadRequest(s"Not file")
        case Some(part) => for {
          contents <- part.body.through(utf8Decode).runFoldMonoid
          response <- Ok(s"""Multipart Data\nParts:${m.parts.length}
                            |File contents: ${contents}""".stripMargin)
        } yield response
      }
    }
   }
  }
 }

前面的代码片段将返回文件的内容。

于 2017-11-18T20:52:41.260 回答