Skip to content
This repository was archived by the owner on Sep 12, 2021. It is now read-only.

Commit 7ea85d9

Browse files
authored
Support for a list of files in a multipart/form-data request (#2)
Please note that this is currently not specified and it may be the case that this changes in a future version of the specification. An upload can be handled with the following definition: - name: files in: formData description: Upload multiple files required: true type: array items: type: File collectionFormat: multi Relates to: OAI/OpenAPI-Specification#254
1 parent ef72dcc commit 7ea85d9

File tree

6 files changed

+36
-15
lines changed

6 files changed

+36
-15
lines changed

clientstub/src/main/scala/com/mohiva/swagger/codegen/TestApi.scala

+16-7
Original file line numberDiff line numberDiff line change
@@ -303,14 +303,23 @@ class TestApi @Inject() (apiInvoker: ApiInvoker) {
303303
/**
304304
* Test if a request with multipart form data will be sent successfully.
305305
*/
306-
def testRequestWithMultipartFormData(file: File, returnFile: Boolean, rc: Config = Config())(
307-
implicit
308-
ec: ExecutionContext): Future[ApiResponse[File]] = {
309-
310-
apiInvoker.execute[File](ApiRequest(RequestMethod.POST, "", "/test", Some("multipart/form-data; charset=utf-8"), rc)
306+
def testRequestWithMultipartFormData(
307+
file: File,
308+
files: Seq[File],
309+
param: String,
310+
returnFile: Boolean,
311+
rc: Config = Config()
312+
)(
313+
implicit
314+
ec: ExecutionContext
315+
): Future[ApiResponse[String]] = {
316+
317+
apiInvoker.execute[String](ApiRequest(RequestMethod.POST, "", "/test", Some("multipart/form-data; charset=utf-8"), rc)
311318
.withFormParam("file", file)
319+
.withFormParam("files", ApiParams.ArrayValues(files, ApiParams.CollectionFormats.MULTI))
320+
.withFormParam("param", param)
312321
.withFormParam("returnFile", returnFile)
313-
.withPrimitiveSuccessResponse[File](200)
322+
.withPrimitiveSuccessResponse[String](200)
314323
)
315324
}
316325

@@ -918,4 +927,4 @@ object TestApi {
918927
def `x-Double`(index: Int = 0) = ApiHeaderExtractor(r.headers).asDouble("X-DOUBLE", index)
919928
def `x-Boolean`(index: Int = 0) = ApiHeaderExtractor(r.headers).asBoolean("X-BOOLEAN", index)
920929
}
921-
}
930+
}

clientstub/src/main/scala/com/mohiva/swagger/codegen/core/ApiImplicits.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ object ApiParams {
134134
implicit class AnyMapNormalizers(val m: Map[String, Any]) {
135135
def normalize: Seq[(String, Any)] = m.mapValues(_.normalize).toSeq.flatMap {
136136
case (name, EmptyValue(_)) => Seq()
137-
case (name, ArrayValues(values, format)) if format == CollectionFormats.MULTI => values.map { v => name -> v }
137+
case (name, ArrayValues(values, format)) if format == CollectionFormats.MULTI =>
138+
m.values.exists(_.isInstanceOf[File]) match {
139+
case false => values.map { v => name -> v }
140+
case true => values.zipWithIndex.map { case (v, i) => name + i.toString -> v }
141+
}
138142
case (k, v) => Seq(k -> v)
139143
}
140144
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TEST
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TEST
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TEST

clientstub/src/test/scala/com/mohiva/swagger/codegen/TestApiSpec.scala

+12-7
Original file line numberDiff line numberDiff line change
@@ -273,16 +273,21 @@ class TestApiSpec extends Specification with NoLanguageFeatures with ContentMatc
273273
"send a request with multipart-form data" in new WithApplication with Context {
274274
val route = Route {
275275
case ("POST", "/test") => Action(parse.multipartFormData) { request =>
276-
val file = request.body.file("file")
277-
val returnFile = request.body.dataParts.get("returnFile").exists(_.exists(_ == "true"))
278-
file -> returnFile match {
279-
case (Some(f), true) => Ok.sendFile(f.ref.file)
280-
case _ => NoContent
281-
}
276+
val file1 = request.body.file("file").map(_.filename).getOrElse(throw new Exception("Not found `file`"))
277+
val file2 = request.body.file("files0").map(_.filename).getOrElse(throw new Exception("Not found `files0`"))
278+
val file3 = request.body.file("files1").map(_.filename).getOrElse(throw new Exception("Not found `files1`"))
279+
val param = request.body.dataParts("param").mkString("")
280+
val returnFile = request.body.dataParts("returnFile").mkString("")
281+
Ok(file1 + "-" + file2 + "-" + file3 + "-" + param + "-" + returnFile)
282282
}
283283
}
284284

285-
await(testApi.testRequestWithMultipartFormData(file("test.txt"), returnFile = true)).content must haveSameLinesAs(file("test.txt"))
285+
await(testApi.testRequestWithMultipartFormData(
286+
file("test1.txt"),
287+
Seq(file("test2.txt"), file("test3.txt")),
288+
"test",
289+
returnFile = true
290+
)).content must be equalTo "test1.txt-test2.txt-test3.txt-test-true"
286291
}
287292

288293
"send a request with form-url-encoded data" in new Context {

0 commit comments

Comments
 (0)