Spring MultipartFile parameter not respecting configured maxFileSize - java

I have a file upload Controller. I'm trying to make the max file size configurable, but I'm not able to figure out why the configuration as documented (https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-multipart-file-upload-configuration) is not being applied.
plugins {
id 'org.springframework.boot' version '2.1.4.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.MultipartConfigElement;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
#Controller
public class FileUploadController {
private MultipartConfigElement multipartConfigElement;
#Autowired
public FileUploadController(MultipartConfigElement multipartConfigElement) {
this.multipartConfigElement = multipartConfigElement;
}
#PostMapping("/upload")
public void upload(#RequestParam("file") MultipartFile file) throws IOException {
InputStream inputStream = new BufferedInputStream(file.getInputStream());
// TODO something with inputStream
long fileSize = file.getSize();
boolean fileSizeLimitExceeded = fileSize > multipartConfigElement.getMaxFileSize();
return;
}
}
Debug screenshot
I expect the multipartConfigElement.getMaxFileSize() should prevent larger files getting this far and automatically return a 400 or some other type of exception.
But instead the maxFileSize seems to be completely ignored.

So it turns out that the limits do work, and do automatically throw Exceptions.
I saw this when I ran a request against my Controller using Postman.
{
"timestamp": "2019-04-05T09:52:39.839+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1 bytes.",
"path": "/upload"
}
The reason I wasn't seeing that was because I was testing with MockMVC (snippet below). MockMVC doesn't seem to trigger the exceptions for some reason – maybe because it is not running on a compatible web server. Probably related to https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-mvc-test-vs-end-to-end-integration-tests.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.io.FileInputStream;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = DemoApplication.class)
#AutoConfigureMockMvc
public class FileUploadTest {
#Autowired
private MockMvc mockMvc;
#Test
public void givenAFileThatExceedsTheLimit_whenUploaded_responseWith400Error() throws Exception {
MockMultipartFile file =
new MockMultipartFile("file", new FileInputStream(TestUtils.loadLargeFile()));
this.mockMvc
.perform(MockMvcRequestBuilders.multipart("/upload").file(file)
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE))
.andExpect(status().isBadRequest());
}
}

As commented by Andrew E, MockMvc won't replicate the max file size that you set with the properties spring.servlet.multipart.max-file-size and spring.servlet.multipart.max-request-size.
I managed to test the file size limite like this (adapted from here https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-running-server)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RunningServerTest {
// my upload endpint requires authentication, so I need to mock the Oauth2 authorization server response
#MockBean private JwtDecoder jwtDecoder;
#Test
void shouldNotUploadMultipartFileGreaterThanMaxAllowedSize(#Autowired WebTestClient webClient) {
// GIVEN
Jwt jwt =
Jwt.withTokenValue("some-bearer-token")
.header("key", "value")
.claim("email", "user_email#example.com")
.build();
when(jwtDecoder.decode("some-bearer-token")).thenReturn(jwt);
ClassPathResource res = new ClassPathResource("file-bigger-than-max-size.txt");
// WHEN + THEN
webClient
.post()
.uri("/upload")
.header("Authorization", "Bearer some-bearer-token")
.header("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE)
.body(BodyInserters.fromResource(res))
.exchange()
.expectStatus()
// you might need to define a custom exception handler
// to map org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException
// to a 400 http error
.isEqualTo(HttpStatus.BAD_REQUEST);
}
}

Related

Why does a 415 response occur when calling the multipart file upload api made with spring webflux?

while creating a file upload api using spring webflux, the response of the api is 415.
I searched hard on Google, but couldn't find a solution, so I posted a question.
My guess is that the conversion of Flux files failed during the message conversion process.
I would be very grateful if you could tell me how to solve it.
I couldn't speak English well, so I had help from Google Translate. I apologize in advance that my tone may be unsporting.
environmental information
jdk17,
gradle 7.6
dependencies
dependencies {
// lombok
compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24'
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24'
// https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.2'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-web'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}
API CODE Example
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#Slf4j
#RestController
#RequestMapping("/v1")
public class FileController {
#PostMapping(value = "/test")
public String test(#RequestPart("test") String temp) {
return null;
}
#PostMapping(value = "/file", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Mono<ResponseEntity<String>> uploadFile(#RequestPart("file") Flux<FilePart> files) {
System.out.println("called uploadFile!!!");
return Mono.empty();
}
}
Test CODE Example
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.FileInputStream;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.mock.web.MockPart;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
#ExtendWith(SpringExtension.class)
#SpringBootTest
public class FileControllerTest {
#Test
#DisplayName("file upload test")
public void uploadFileTest() throws Exception {
// given
String fileName = "TestSample";
String origFilename = "TestSample.md";
Path sampleFilePath = Paths.get(getClass().getResource("sample/" + origFilename + "").toURI());
FileInputStream fis = new FileInputStream(sampleFilePath.toFile());
MockMultipartFile sampleFile = new MockMultipartFile(fileName,
origFilename, MediaType.MULTIPART_FORM_DATA_VALUE, fis);
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new FileController()).build();
// when, then
mockMvc.perform(
multipart(new URI("/v1/file")).file(
sampleFile).part(
new MockPart("file",
sampleFile.getBytes())))
.andExpect(status().isOk());
}
}
Response Example
2023-02-02T11:45:45.114+09:00 WARN 36696 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/octet-stream' is not supported]

Unable to run JUnit5 PACT test. No method annotated with #Pact was found on test class ConsumerContractTest for provider ''

I'm trying to get a PACT test running on JUnit5. We use JUnit4 for others, but this one will be JUnit5. The error occurs when running the JUnit5 test using the pact annotation on the RequestResponsePact method.
Error : No method annotated with #Pact was found on test class ConsumerContractTest for provider ''.
I've seen Basic Pact/Junit5 Test Setup fails. No method annotated with #Pact was found for provider error, but this is issue was due to the #PactTestFor(pactMethod = "examplePact") not matching the #Pact method name. But on my code it does match.
I can't seem to figure out why I get the error and especially why the error has an empty provider(provider '') despite defining one("some-provider").
Example code :
import au.com.dius.pact.consumer.MockServer
import au.com.dius.pact.consumer.Pact
import au.com.dius.pact.consumer.dsl.PactDslJsonArray
import au.com.dius.pact.consumer.dsl.PactDslWithProvider
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt
import au.com.dius.pact.consumer.junit5.PactTestFor
import au.com.dius.pact.model.RequestResponsePact
import groovyx.net.http.RESTClient
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.http.HttpStatus
#ExtendWith(PactConsumerTestExt.class)
class ConsumerContractTest {
#Pact(consumer = "some-consumer", provider = "some-provider")
RequestResponsePact examplePact(PactDslWithProvider builder) {
builder
.given("provider state")
.uponReceiving("Contract description")
.method("GET")
.matchPath("/endpoint")
.willRespondWith()
.status(200)
.headers(["Content-Type": "application/vnd.pnf.v1+json"])
.body(new PactDslJsonArray())
.toPact()
}
#Test
#PactTestFor(pactMethod = "examplePact")
void exampleTest(MockServer mockServer) {
def client = new RESTClient(mockServer.getUrl())
}
}
Not sure if that's just the gist you've posted here but I see the return word missing and also the #PactTestFor annotation missing the provider and version. Here is an example I have that works for my project.
import au.com.dius.pact.consumer.dsl.DslPart;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
import au.com.dius.pact.consumer.junit5.PactTestFor;
import au.com.dius.pact.core.model.PactSpecVersion;
import au.com.dius.pact.core.model.RequestResponsePact;
import au.com.dius.pact.core.model.annotations.Pact;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import java.util.HashMap;
import java.util.Map;
import static com.example.mbbackend.config.Constants.*;
import static com.example.mbbackend.util.Utils.getRequestSpecification;
import static org.junit.jupiter.api.Assertions.assertEquals;
#ExtendWith(PactConsumerTestExt.class)
class GetActorIT {
Map<String, String> headers = new HashMap<>();
String path = "/api/mb/actor/";
#Pact(provider = PACT_PROVIDER, consumer = PACT_CONSUMER)
public RequestResponsePact createPact(PactDslWithProvider builder) {
headers.put("Content-Type", "application/json");
DslPart bodyReturned = new PactDslJsonBody()
.uuid("id", "1bfff94a-b70e-4b39-bd2a-be1c0f898589")
.stringType("name", "A name")
.stringType("family", "A family")
.stringType("imageUrl", "http://anyimage.com")
.close();
return builder
.given("A request to retrieve an actor")
.uponReceiving("A request to retrieve an actor")
.pathFromProviderState(path + "${actorId}", path + "1bfff94a-b70e-4b39-bd2a-be1c0f898589")
.method("GET")
.headers(headers)
.willRespondWith()
.status(200)
.body(bodyReturned)
.toPact();
}
#Test
#PactTestFor(providerName = PACT_PROVIDER, port = PACT_PORT, pactVersion = PactSpecVersion.V3)
void runTest() {
//Mock url
RequestSpecification rq = getRequestSpecification().baseUri(MOCK_PACT_URL).headers(headers);
Response response = rq.get(path + "1bfff94a-b70e-4b39-bd2a-be1c0f898589");
assertEquals(200, response.getStatusCode());
}
}

Feign does not resolve name

I am trying t call another service using Spring Cloud's Open Feign but here is the response I keep getting:
{
"timestamp": 1579015052962,
"status": 500,
"error": "Internal Server Error",
"message": "auth-service: Name or service not known executing GET http://auth-service/api/v1/auth",
"path": "/api/v1/event"
}
Here's my code:
package com.eventmanager.events.client;
import com.eventmanager.events.client.mappings.Auth;
import com.eventmanager.events.config.CustomFeignClientConfig;
import com.eventmanager.events.responses.Response;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
#FeignClient(name = "auth-service", configuration = CustomFeignClientConfig.class)
public interface AuthClient {
#GetMapping("/api/v1/auth")
public Response<Auth> getLoggedUser(#RequestHeader(value = "Authorization") String authorization);
}
I configured Feign to use the OkHttp client and I'm not sure if it's responsible for the error:
package com.eventmanager.events.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.okhttp.OkHttpClient;
#Configuration
public class CustomFeignClientConfig {
#Bean
public OkHttpClient client() {
return new OkHttpClient();
}
}
If you are using Finchey.SR1, You can check this https://stackoverflow.com/a/52727544
There seems to be an issue with ContentPath in that cloud version.
May be because you have not specified base URL. for client & it is taking base URL as auth-service.
#FeignClient(name = "auth-service", configuration = CustomFeignClientConfig.class, url = "http://lcoalhost:8080")
public interface AuthClient {
#GetMapping("/api/v1/auth")
public Response<Auth> getLoggedUser(#RequestHeader(value = "Authorization") String authorization);
}
Guess I'm a little late to the party. The following dependency can be added to your pom.xml file. If you you have feign-okhttp dependency then you should be having this dependency by default.
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>5.0.0-alpha.6</version>
</dependency>
Now instead of importing feign.okhttp.OkHttpClient; import okhttp3.OkHttpClient.
So your class should look like below.
package com.eventmanager.events.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import okhttp3.OkHttpClient;
#Configuration
public class CustomFeignClientConfig {
#Bean
public OkHttpClient client() {
return new OkHttpClient();
}
}
Also consider adding the below entry in your application.properties file. This will stop Feign from using the default http client.
feign.httpclient.enabled=false
You may refer to this post for more information

Spring WebFlux File Upload: Unsupported Media Type 415 with Multipart upload

I'm running into some issues handling a file upload using spring's reactive framework. I think I'm following the docs, but can't get away from this 415 / Unsupported Media Type issue.
My controller looks like below (as per the example here: https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-multipart-forms)
package com.test.controllers;
import reactor.core.publisher.Flux;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class TestController {
#RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> uploadHandler(#RequestBody Flux<Part> parts) {
return parts
.filter(part -> part instanceof FilePart)
.ofType(FilePart.class)
.log()
.flatMap(p -> Flux.just(p.filename()));
}
}
POSTing to this endpoint though, always gives me the same output:
curl -X POST -F "data=#basic.ppt" http://localhost:8080/upload
---
"Unsupported Media Type","message":"Content type 'multipart/form-data;boundary=------------------------537139718d79303c;charset=UTF-8' not supported"
I've attempted to use #RequestPart("data") too, but get a similar Unsupported Media Type error, albeit with the content type of the file.
It seems that Spring is having issues converting these to a Part..? I'm stuck - any help is apprecitated!
Well, it's not a direct answer for your question, because I use functional endpoints, but I hope it will help you somehow.
import org.springframework.context.annotation.Bean;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.stereotype.Controller;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import java.io.File;
import java.util.Map;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
#Controller
public class FileUploadController {
#Bean
RouterFunction<ServerResponse> apiRoutes() {
return nest(path("/api"),
route(POST("/upload"), fileUpload()));
}
private HandlerFunction<ServerResponse> fileUpload() {
return request -> {
return request.body(BodyExtractors.toMultipartData()).flatMap(parts -> {
Map<String, Part> map = parts.toSingleValueMap();
final FilePart filePart = (FilePart) map.get("file");
final String dir = "C:\\JDeveloper\\mywork\\Spring\\SpringTest\\webflux-file-upload\\uploaded";
filePart.transferTo(new File(dir + "/" + filePart.filename()));
return ServerResponse.ok().body(fromObject("ok, file uploaded"));
}
);
};
}
}
You can upload a file with curl like this:
curl -F "file=#C:\Users\Wojtek\Desktop\img-5081775796112008742.jpg" localhost:8080/api/fileupload
Thanks #kojot for your answer, but in this case I discovered the issue was my inclusion of spring-webmvc transiently in addition to spring-webflux. Your solution would likely have worked too, but I wanted to stick with the Controller style so ended up forcibly excluding spring-webmvc from my build.gradle:
configurations {
implementation {
exclude group: 'org.springframework', module: 'spring-webmvc'
}
}
After that it worked as documented.

spring boot multipartFile with application/octet-stream throws exception

I wanted to build a simple Rest api using Spring boot which accepts any given file and then performs some operations on it . I went through the spring examples on multipartFile https://spring.io/guides/gs/uploading-files/ and I decided to follow the same approach. The files that will be uploaded through my rest api will have some specific extension. So,i gave the content-type as application/octet-stream . When I try to run my unit test cases for the same,
I always get the exception of
nested exception is org.springframework.web.multipart.MultipartException: The current request is not a multipart request
This exception does not appear if the content type is text/plain or if there is no 'consumes' parameter in the requestMapping.
My controller code looks as follows :
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
#Controller
#RequestMapping("/v1/sample")
public class SampleController {
private static Logger log = LoggerFactory.getLogger(SampleController.class);
#RequestMapping(path = "/{id}/upload",
consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE},
method = RequestMethod.POST)
public ResponseEntity<String> uploadfile(#PathVariable String id,
#RequestParam("file") MultipartFile upgradeFile) {
log.info("Obtained a upload request for the id {}",id );
return new ResponseEntity<String>("file upload has been accepted.",
HttpStatus.ACCEPTED);
}
}
And my unit test snippet is as follows :
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import com.stellapps.devicemanager.fota.Application;
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#SpringApplicationConfiguration(classes = Application.class)
#EnableWebMvc
public class ControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Before
public void mockMvcBuilder() {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
#Test
public void test_ValidPayload() {
String uri = "/v1/sample/1234/upload";
Path path = Paths.get("src/test/resources/someFile");
try {
byte[] bytes = Files.readAllBytes(path);
MockMultipartFile multipartFile =
new MockMultipartFile("file", "someFile.diff", "application/octet-stream", bytes);
mockMvc.perform(fileUpload(uri).file(multipartFile).contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
.andExpect(status().isAccepted());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
If I use text/plain as the content-type and i give a normal text file, it goes through fine. If I add the content-type as application/octet-stream it throws the following exception
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.web.multipart.MultipartException: The current request is not a multipart request
at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.assertIsMultipartRequest(RequestPartMethodArgumentResolver.java:204)
at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.resolveArgument(RequestPartMethodArgumentResolver.java:129)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
How Do I make my request accept application/octet-stream and what changes should I make to the test case to ensure it succeeds.
UPDATE:
Removing the consumes header and by not specifying the content-type in MockPartFile is one of the way to upload a file. I suppose by default the controller takes it as application/octet-stream
UPDATE:
Thank you for the response. I was using an earlier version of spring (1.3.1) and after going through the answer, I updated my spring version and the test case to match it and It started working.
Try below steps
Remove the consumes from the RequestMapping attributes.
MockMultipartFile multipartFile = new MockMultipartFile("file","somename","multipart/form-data", fileinputstream);
Change to MockMvc:
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/sample/1234/payload")
.file(multipartFile)
.andExpect(status().isOk());
For help check
Upload file using Spring mvc and MockMVC
EDIT:
I've tried a sample spring-boot-rest app with your scenario. Seems application/octet-stream is no issue. Please check my repo
https://github.com/satya-j/boot-file-manager

Categories