Browse Source
Also add test with Optional parameter for a RequestPart argument. See gh-31164 Signed-off-by: Dmitrii Bocharov <bdshadow@gmail.com>pull/31202/head
5 changed files with 97 additions and 164 deletions
@ -1,63 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2023 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.web.service.invoker; |
|
||||||
|
|
||||||
import java.util.Optional; |
|
||||||
|
|
||||||
import org.springframework.core.MethodParameter; |
|
||||||
import org.springframework.http.HttpEntity; |
|
||||||
import org.springframework.http.HttpHeaders; |
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* {@link HttpServiceArgumentResolver} for arguments of type {@link MultipartFile}. |
|
||||||
* The argument is recognized by type, and does not need to be annotated. To make |
|
||||||
* it optional, declare the parameter with an {@link Optional} wrapper. |
|
||||||
* |
|
||||||
* @author Olga Maciaszek-Sharma |
|
||||||
* @author Rossen Stoyanchev |
|
||||||
* @since 6.1 |
|
||||||
*/ |
|
||||||
public class MultipartFileArgumentResolver extends AbstractNamedValueArgumentResolver { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { |
|
||||||
Class<?> type = parameter.nestedIfOptional().getNestedParameterType(); |
|
||||||
return (type.equals(MultipartFile.class) ? |
|
||||||
new NamedValueInfo("", true, null, "MultipartFile", true) : null); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void addRequestValue( |
|
||||||
String name, Object value, MethodParameter parameter, HttpRequestValues.Builder values) { |
|
||||||
|
|
||||||
Assert.state(value instanceof MultipartFile, "Expected MultipartFile value"); |
|
||||||
MultipartFile file = (MultipartFile) value; |
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders(); |
|
||||||
if (file.getOriginalFilename() != null) { |
|
||||||
headers.setContentDispositionFormData(name, file.getOriginalFilename()); |
|
||||||
} |
|
||||||
if (file.getContentType() != null) { |
|
||||||
headers.add(HttpHeaders.CONTENT_TYPE, file.getContentType()); |
|
||||||
} |
|
||||||
|
|
||||||
values.addRequestPart(name, new HttpEntity<>(file.getResource(), headers)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,96 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2023 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.web.service.invoker; |
|
||||||
|
|
||||||
import java.util.Optional; |
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
|
|
||||||
import org.springframework.http.HttpEntity; |
|
||||||
import org.springframework.http.HttpHeaders; |
|
||||||
import org.springframework.http.MediaType; |
|
||||||
import org.springframework.util.MultiValueMap; |
|
||||||
import org.springframework.web.bind.annotation.RequestPart; |
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
import org.springframework.web.service.annotation.PostExchange; |
|
||||||
import org.springframework.web.testfixture.servlet.MockMultipartFile; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
/** |
|
||||||
* Unit tests for {@link MultipartFileArgumentResolver}. |
|
||||||
* Tests for base class functionality of this resolver can be found in |
|
||||||
* {@link NamedValueArgumentResolverTests}. |
|
||||||
* |
|
||||||
* @author Olga Maciaszek-Sharma |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
class MultipartFileArgumentResolverTests { |
|
||||||
|
|
||||||
private final TestExchangeAdapter client = new TestExchangeAdapter(); |
|
||||||
|
|
||||||
private final MultipartService multipartService = |
|
||||||
HttpServiceProxyFactory.builderFor(this.client).build().createClient(MultipartService.class); |
|
||||||
|
|
||||||
|
|
||||||
@Test |
|
||||||
void multipartFile() { |
|
||||||
String fileName = "testFileName"; |
|
||||||
String originalFileName = "originalTestFileName"; |
|
||||||
MultipartFile testFile = new MockMultipartFile(fileName, originalFileName, "text/plain", "test".getBytes()); |
|
||||||
|
|
||||||
this.multipartService.postMultipartFile(testFile); |
|
||||||
Object value = this.client.getRequestValues().getBodyValue(); |
|
||||||
|
|
||||||
assertThat(value).isInstanceOf(MultiValueMap.class); |
|
||||||
MultiValueMap<String, HttpEntity<?>> map = (MultiValueMap<String, HttpEntity<?>>) value; |
|
||||||
assertThat(map).hasSize(1); |
|
||||||
|
|
||||||
HttpEntity<?> entity = map.getFirst("file"); |
|
||||||
assertThat(entity).isNotNull(); |
|
||||||
assertThat(entity.getBody()).isEqualTo(testFile.getResource()); |
|
||||||
|
|
||||||
HttpHeaders headers = entity.getHeaders(); |
|
||||||
assertThat(headers.getContentType()).isEqualTo(MediaType.TEXT_PLAIN); |
|
||||||
assertThat(headers.getContentDisposition().getType()).isEqualTo("form-data"); |
|
||||||
assertThat(headers.getContentDisposition().getName()).isEqualTo("file"); |
|
||||||
assertThat(headers.getContentDisposition().getFilename()).isEqualTo(originalFileName); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
void optionalMultipartFile() { |
|
||||||
this.multipartService.postOptionalMultipartFile(Optional.empty(), "anotherPart"); |
|
||||||
Object value = client.getRequestValues().getBodyValue(); |
|
||||||
|
|
||||||
assertThat(value).isInstanceOf(MultiValueMap.class); |
|
||||||
MultiValueMap<String, HttpEntity<?>> map = (MultiValueMap<String, HttpEntity<?>>) value; |
|
||||||
assertThat(map).containsOnlyKeys("anotherPart"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") |
|
||||||
private interface MultipartService { |
|
||||||
|
|
||||||
@PostExchange |
|
||||||
void postMultipartFile(MultipartFile file); |
|
||||||
|
|
||||||
@PostExchange |
|
||||||
void postOptionalMultipartFile(Optional<MultipartFile> file, @RequestPart String anotherPart); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue