1
1
/*
2
- * Copyright 2002-2020 the original author or authors.
2
+ * Copyright 2002-2022 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
32
32
import javax .servlet .http .Part ;
33
33
34
34
import org .junit .jupiter .api .Test ;
35
+ import org .junit .jupiter .params .ParameterizedTest ;
36
+ import org .junit .jupiter .params .provider .ValueSource ;
35
37
36
- import org .springframework .http .MediaType ;
37
38
import org .springframework .mock .web .MockMultipartFile ;
38
39
import org .springframework .mock .web .MockPart ;
39
40
import org .springframework .stereotype .Controller ;
40
41
import org .springframework .test .web .servlet .MockMvc ;
42
+ import org .springframework .test .web .servlet .request .MockMultipartHttpServletRequestBuilder ;
41
43
import org .springframework .ui .Model ;
42
44
import org .springframework .util .StreamUtils ;
43
- import org .springframework .validation .BindException ;
44
45
import org .springframework .validation .BindingResult ;
45
46
import org .springframework .web .bind .annotation .RequestMapping ;
46
47
import org .springframework .web .bind .annotation .RequestMethod ;
63
64
*/
64
65
public class MultipartControllerTests {
65
66
66
- @ Test
67
- public void multipartRequestWithSingleFile () throws Exception {
67
+ @ ParameterizedTest
68
+ @ ValueSource (strings = {"/multipartfile" , "/part" })
69
+ public void multipartRequestWithSingleFileOrPart (String url ) throws Exception {
68
70
byte [] fileContent = "bar" .getBytes (StandardCharsets .UTF_8 );
69
- MockMultipartFile filePart = new MockMultipartFile ("file" , "orig" , null , fileContent );
70
71
71
72
byte [] json = "{\" name\" :\" yeeeah\" }" .getBytes (StandardCharsets .UTF_8 );
72
73
MockMultipartFile jsonPart = new MockMultipartFile ("json" , "json" , "application/json" , json );
73
74
75
+ MockMultipartHttpServletRequestBuilder requestBuilder = (url .endsWith ("file" ) ?
76
+ multipart (url ).file (new MockMultipartFile ("file" , "orig" , null , fileContent )) :
77
+ multipart (url ).part (new MockPart ("part" , "orig" , fileContent )));
78
+
74
79
standaloneSetup (new MultipartController ()).build ()
75
- .perform (multipart ( "/multipartfile" ). file ( filePart ) .file (jsonPart ))
80
+ .perform (requestBuilder .file (jsonPart ))
76
81
.andExpect (status ().isFound ())
77
82
.andExpect (model ().attribute ("fileContent" , fileContent ))
78
83
.andExpect (model ().attribute ("jsonContent" , Collections .singletonMap ("name" , "yeeeah" )));
@@ -229,65 +234,16 @@ public void multipartRequestWithOptionalFileListNotPresent() throws Exception {
229
234
}
230
235
231
236
@ Test
232
- public void multipartRequestWithParts_resolvesMultipartFileArguments () throws Exception {
233
- byte [] fileContent = "bar" .getBytes (StandardCharsets .UTF_8 );
234
- MockPart filePart = new MockPart ("file" , "orig" , fileContent );
235
-
236
- byte [] json = "{\" name\" :\" yeeeah\" }" .getBytes (StandardCharsets .UTF_8 );
237
- MockPart jsonPart = new MockPart ("json" , json );
238
- jsonPart .getHeaders ().setContentType (MediaType .APPLICATION_JSON );
239
-
240
- standaloneSetup (new MultipartController ()).build ()
241
- .perform (multipart ("/multipartfile" ).part (filePart ).part (jsonPart ))
242
- .andExpect (status ().isFound ())
243
- .andExpect (model ().attribute ("fileContent" , fileContent ))
244
- .andExpect (model ().attribute ("jsonContent" , Collections .singletonMap ("name" , "yeeeah" )));
245
- }
246
-
247
- @ Test
248
- public void multipartRequestWithParts_resolvesPartArguments () throws Exception {
237
+ public void multipartRequestWithDataBindingToFile () throws Exception {
249
238
byte [] fileContent = "bar" .getBytes (StandardCharsets .UTF_8 );
250
239
MockPart filePart = new MockPart ("file" , "orig" , fileContent );
251
240
252
- byte [] json = "{\" name\" :\" yeeeah\" }" .getBytes (StandardCharsets .UTF_8 );
253
- MockPart jsonPart = new MockPart ("json" , json );
254
- jsonPart .getHeaders ().setContentType (MediaType .APPLICATION_JSON );
255
-
256
241
standaloneSetup (new MultipartController ()).build ()
257
- .perform (multipart ("/part" ).part (filePart ).part (jsonPart ))
258
- .andExpect (status ().isFound ())
259
- .andExpect (model ().attribute ("fileContent" , fileContent ))
260
- .andExpect (model ().attribute ("jsonContent" , Collections .singletonMap ("name" , "yeeeah" )));
261
- }
262
-
263
- @ Test
264
- public void multipartRequestWithParts_resolvesMultipartFileProperties () throws Exception {
265
- byte [] fileContent = "bar" .getBytes (StandardCharsets .UTF_8 );
266
- MockPart filePart = new MockPart ("file" , "orig" , fileContent );
267
-
268
- standaloneSetup (new MultipartController ()).build ()
269
- .perform (multipart ("/multipartfileproperty" ).part (filePart ))
242
+ .perform (multipart ("/multipartfilebinding" ).part (filePart ))
270
243
.andExpect (status ().isFound ())
271
244
.andExpect (model ().attribute ("fileContent" , fileContent ));
272
245
}
273
246
274
- @ Test
275
- public void multipartRequestWithParts_cannotResolvePartProperties () throws Exception {
276
- byte [] fileContent = "bar" .getBytes (StandardCharsets .UTF_8 );
277
- MockPart filePart = new MockPart ("file" , "orig" , fileContent );
278
-
279
- Exception exception = standaloneSetup (new MultipartController ()).build ()
280
- .perform (multipart ("/partproperty" ).part (filePart ))
281
- .andExpect (status ().is4xxClientError ())
282
- .andReturn ()
283
- .getResolvedException ();
284
-
285
- assertThat (exception ).isNotNull ();
286
- assertThat (exception ).isInstanceOf (BindException .class );
287
- assertThat (((BindException ) exception ).getFieldError ("file" ))
288
- .as ("MultipartRequest would not bind Part properties." ).isNotNull ();
289
- }
290
-
291
247
@ Test // SPR-13317
292
248
public void multipartRequestWrapped () throws Exception {
293
249
byte [] json = "{\" name\" :\" yeeeah\" }" .getBytes (StandardCharsets .UTF_8 );
@@ -391,11 +347,11 @@ public String processOptionalFileList(@RequestParam Optional<List<MultipartFile>
391
347
}
392
348
393
349
@ RequestMapping (value = "/part" , method = RequestMethod .POST )
394
- public String processPart (@ RequestPart Part file ,
350
+ public String processPart (@ RequestPart Part part ,
395
351
@ RequestPart Map <String , String > json , Model model ) throws IOException {
396
352
397
- if (file != null ) {
398
- byte [] content = StreamUtils .copyToByteArray (file .getInputStream ());
353
+ if (part != null ) {
354
+ byte [] content = StreamUtils .copyToByteArray (part .getInputStream ());
399
355
model .addAttribute ("fileContent" , content );
400
356
}
401
357
model .addAttribute ("jsonContent" , json );
@@ -409,9 +365,9 @@ public String processMultipart(@RequestPart Map<String, String> json, Model mode
409
365
return "redirect:/index" ;
410
366
}
411
367
412
- @ RequestMapping (value = "/multipartfileproperty " , method = RequestMethod .POST )
413
- public String processMultipartFileBean (MultipartFileBean multipartFileBean , Model model , BindingResult bindingResult )
414
- throws IOException {
368
+ @ RequestMapping (value = "/multipartfilebinding " , method = RequestMethod .POST )
369
+ public String processMultipartFileBean (
370
+ MultipartFileBean multipartFileBean , Model model , BindingResult bindingResult ) throws IOException {
415
371
416
372
if (!bindingResult .hasErrors ()) {
417
373
MultipartFile file = multipartFileBean .getFile ();
@@ -421,20 +377,6 @@ public String processMultipartFileBean(MultipartFileBean multipartFileBean, Mode
421
377
}
422
378
return "redirect:/index" ;
423
379
}
424
-
425
- @ RequestMapping (value = "/partproperty" , method = RequestMethod .POST )
426
- public String processPartBean (PartBean partBean , Model model , BindingResult bindingResult )
427
- throws IOException {
428
-
429
- if (!bindingResult .hasErrors ()) {
430
- Part file = partBean .getFile ();
431
- if (file != null ) {
432
- byte [] content = StreamUtils .copyToByteArray (file .getInputStream ());
433
- model .addAttribute ("fileContent" , content );
434
- }
435
- }
436
- return "redirect:/index" ;
437
- }
438
380
}
439
381
440
382
private static class MultipartFileBean {
@@ -450,18 +392,6 @@ public void setFile(MultipartFile file) {
450
392
}
451
393
}
452
394
453
- private static class PartBean {
454
-
455
- private Part file ;
456
-
457
- public Part getFile () {
458
- return file ;
459
- }
460
-
461
- public void setFile (Part file ) {
462
- this .file = file ;
463
- }
464
- }
465
395
466
396
private static class RequestWrappingFilter extends OncePerRequestFilter {
467
397
0 commit comments