spring boot upload file allow only images - spring

#Controller
public class UploadController {
#PostMapping("/upload")
public String upload(#RequestParam("file") MultipartFile file) {
// save
}
}
How to specify/config that only images(jpeg, png) are allowed to be uploaded?

You should do a check on file.getContentType() if it matches "image/jpeg" or "image/png". Not sure if consumes property of the #PostMapping would work because the request is of type "multipart/form-data" or "application/x-www-form-urlencoded" it seems.

Related

Required request part 'file' is not present in Spring Boot

I checked all of the simular posts and still couldnt find the solution.
Problem is Required request part 'file' is not present in test class.
I want to upload a file and save it to the database. Here is my rest controller #RestController:
#PostMapping(value = "/upload")
public ResponseEntity<LogoDto> uploadLogo(#RequestParam("file") MultipartFile multipartFile) {
return ResponseEntity.ok(logoService.createLogo(multipartFile));
}
and my test class:
#Test
public void createLogo2() throws Exception {
String toJsonLogoDto = new Gson().toJson(logoDto);
MockMultipartFile file = new MockMultipartFile("path", "url", MediaType.APPLICATION_JSON_VALUE, image);
LogoDto response = LogoDataTest.validLogoDto();
Mockito.when(logoServiceMock.createLogo(Mockito.any(MultipartFile.class))).thenReturn(response);
mockMvc.perform(MockMvcRequestBuilders.multipart("/brand-icon/upload")
.file(file)
.content(MediaType.APPLICATION_JSON_VALUE)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.characterEncoding(CharEncoding.UTF_8))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk());
}
and my application.yml looks like this:
spring:
servlet:
multipart:
enabled: true
max-file-size: 2MB
max-request-size: 10MB
I tried to add consumes in my #PostMapping;
try to set literally every MediaTypes.. still get an error.
I appreciate all of your answer.
issue is in declaration of MockMultipartFile, first parameter should match controller #RequestParam param. So, in your case, should be:
MockMultipartFile file = new MockMultipartFile("file", "url", MediaType.APPLICATION_JSON_VALUE, image);
Also, I recommend to update your controller method to the following one:
#PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<LogoDto> uploadLogo(#RequestPart("file") MultipartFile multipartFile) {
...
}

Unable to upload file due to Content-Type "multipart/form-data" not set for request body of type StandardMultipartFile

I have a remote service A which does the file upload. I have service B which calls the upload API of service A through FeignClient to upload a file
The method definition in Service A is something like
ResponseEntity<?> upload(#RequestPart("file") MultipartFile file) { }
And the method in Service B is
#FeignClient(url = "http://localhost:5000/")
public interface uploadService {
#RequestMapping(method = RequestMethod.POST, value = "/serviceA/upload")
#Headers("Content-Type: multipart/form-data")
void uploadFile(#RequestPart("file") MultipartFile file);
}
I am getting the error
Content-Type "multipart/form-data" not set for request body of type StandardMultipartFile
I have tried most of the suggestions on https://github.com/spring-cloud/spring-cloud-netflix/issues/867 and
https://github.com/OpenFeign/feign-form but nothing works for me
I was able to solve this issue by simply adding consumes = "multipart/form-data" in the RequestMapping. The reason was that I was mixing spring based annotations with open feign annotations. #Headers("Content-Type: multipart/form-data") works with Open feign. Here I am using spring-cloud-openfeign which provides abstraction to Open feign and make it easy to integration with spring framework components.
#FeignClient(url = "http://localhost:5000/")
public interface uploadService {
#RequestMapping(method = RequestMethod.POST, value = "/serviceA/upload" consumes = "multipart/form-data" )
void uploadFile(#RequestPart("file") MultipartFile file);
}
If you have trouble just within the test just use org.springframework.mock.web.MockMultipartFile where you can set contentType as one of argument in construtor.

File upload in spring webflux - Required MultipartFile parameter 'file' is not present

I'm trying to upload a file using Spring Webflux, but I'm getting the error Required MultipartFile parameter 'file' is not present.
#RestController
#RequestMapping("/documents")
class MyController(val myService: MyService) {
#PostMapping
fun create(#RequestParam("file") file: MultipartFile): Mono<ResponseEntity<Map<String, String>>> {
return myService.create()
}
}
I've also tried replacing #RequestParam("file") file: MultipartFile with ServerRequeset, but I get the error:
"Failed to resolve argument 0 of type 'org.springframework.web.reactive.function.server.ServerRequest' on public reactor.core.publisher.Mono>> co.example.controllers.MyController.create(org.springframework.web.reactive.function.server.ServerRequest)"
Changing to FilePart from MultipartFile is what ended up working for me :)
#RestController
#RequestMapping("/v1/uploads")
class UploadsController(val exampleService: ExampleService) {
#PostMapping(consumes = ["multipart/form-data"])
fun create(#RequestPart("file") filePart: FilePart) = exampleService.save(filePart)
}

#RestController accepting unwanted tags also

I created a spring REST web service using spring boot. It accepts XML in requestbody. The problem is, it accepting unwanted tags also and giving the results, which I want to restrict and notify user about this.
How can i validate the request body (xml) against xsd before it reaches controller or by any other way. Please suggest.
Controller:
#PostMapping(value = "/webservice/{text}", produces = { MediaType.APPLICATION_XML_VALUE })
public ServiceResult processRequest(#PathVariable("text") String text,
#RequestBody Request Request) {
Beans:
#XmlRootElement(name="Request")
#XmlType(propOrder = {"requestHeader", "requestBody"})
public class Request implements Serializable {
private RequestHeader requestHeader;
private RequestBody requestBody;
#XmlElement(name="RequestHeader")
public RequestHeader getRequestHeader() {
return requestHeader;
}
public void setRequestHeader(RequestHeader requestHeader) {
this.requestHeader = requestHeader;
}
#XmlElement(name="RequestBody")
public RequestBody getRequestBody() {
return requestBody;
}
public void setRequestBody(RequestBody requestBody) {
this.requestBody = requestBody;
}
}
Then you might want to fail on unwanted tags: https://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/DeserializationFeature.html#FAIL_ON_UNKNOWN_PROPERTIES
Also, if you can make use of bean validation to validate the values. However, this validation has nothing to do with xsd
Adding the below property to application.properties files solved my problem.
spring.jackson.deserialization.fail-on-unknown-properties=true

Sending file to Spring Boot REST using Axios

I am trying to send a csv file to my java spring boot backend. The code to send my file is below:
var url = 'http://localhost:3001/UploadFile';
var file = this.state.file;
var formData = new FormData();
formData.append("file", file);
axios.post(url, formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
And the code to accept my file from Spring Boot:
#CrossOrigin
#RequestMapping("/UploadFile")
#ResponseBody
public void uploadFile(#RequestParam("file") MultipartFile file) {
}
However, it doesn't seem to work. I keep getting an error saying that the 'Current request is not a multipart request'. Any ideas?
It's not sufficient to specify content-type in frontend you need to do it in controller as well.
You should tell to spring controller what it should consume and also it would be nice to set RequestMethod as POST like this:
#CrossOrigin
#RequestMapping("/UploadFile")
#ResponseBody
public void uploadFile(#RequestParam("file") MultipartFile file, method = RequestMethod.POST, consumes = "multipart/form-data") {
}

Resources