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

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)
}

Related

How to request body object included file in Array at Spring boot

I'm in trouble
How do I get the following data format in Spring Boot?
Example:
[
{name:"fileName", file: file1},
{name:"fileName", file: file2},
{name:"fileName", file: file3},
....
]
use produces in post call like below:
#PostMapping(value = "/save", produces=MediaType. APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType. APPLICATION_OCTET_STREAM_VALUE)
public void updateCharacters(#RequestBody List<Character> character) {
log.log(Level.INFO, "{} characters have been saved", characters.getCharacters().size());
}

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) {
...
}

Junit test for #RequestPart

Here I want to write a test for following controller method for a spring-boot application, on executing method of the test class I'm getting an error Bad Request: Required request part 'formData' is not present, I've tried finding a solution for testing an object having 'RequestPart' annotation but no luck
//method needs to be tested
#PostMapping("/user")
public ResponseEntity<UserDTO> createUser(#RequestPart(value = "files", required= false) MultipartFile[] files,
#RequestPart("formData") UserDTO userDTO) throws URISyntaxException {
userService.save(userDTO, files);
}
// Inside testclass
#BeforeEach
public void initTest()
{
user = createEntity(em);// inside this method I've set all the properties of user object
}
public void createUser() throws Exception {
UserDTO userDTO = userMapper.toDto(user);
mockMvc
.perform(post("/api/user")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(userDTO)))
.andExpect(status().isCreated());
}
You have to build a multipart request using MockMultipartFile with something like this:
MockMultipartFile api = new MockMultipartFile (
"file",
"foo.zip",
"application/zip", "foo".bytes)
and then use it like this:
mvc.perform (
multipart ('/api/foo')
.file (api))
.andExpect(...)
This is for a file upload (groovy code), so you have to adjust it a little bit.

spring boot upload file allow only images

#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.

POST Request to upload multipart file in Spring Boot

I'm using spring boot, I need to upload a multipart file (jpg or png file). I need to send a (POST request to upload the multi part file using "postman"), can anyone provide a screen shot of "postman" of how to set it up to do that or tell me? Thanks.
method :
#RequestMapping(method = RequestMethod.POST, value = "/upload")
#ResponseBody
ResponseEntity<?> writeUserProfilePhoto(#PathVariable Long user, #RequestPart("file") MultipartFile file) throws Throwable {
byte bytesForProfilePhoto[] = FileCopyUtils.copyToByteArray(file.getInputStream()); //Return an InputStream to read the contents of the file from.
this.crmService.writeUserProfilePhoto(user, MediaType.parseMediaType(file.getContentType()),bytesForProfilePhoto);
HttpHeaders httpHeaders = new HttpHeaders();
URI uriOfPhoto = ServletUriComponentsBuilder.fromCurrentContextPath()
.pathSegment(("/users" + "/{user}" + "/photo").substring(1))
.buildAndExpand(Collections.singletonMap("user", user)).toUri();
httpHeaders.setLocation(uriOfPhoto);
return new ResponseEntity<>(httpHeaders, HttpStatus.CREATED);
}
and this is how I sent the POST request:
my configuration class:
#Configuration
#ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
#ConditionalOnProperty(prefix = "multipart", name = "enabled", matchIfMissing = true)
#EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {
#Autowired
private MultipartProperties multipartProperties = new MultipartProperties();
#Bean
#ConditionalOnMissingBean
public MultipartConfigElement multipartConfigElement() {
return this.multipartProperties.createMultipartConfig();
}
#Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
#ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
}
The error in postman says
Required MultipartFile parameter 'file' is not present
The method signature looks fine defining file parameter:
ResponseEntity<?> writeUserProfilePhoto(
#PathVariable Long user, #RequestPart("file") MultipartFile file)
throws Throwable
The issue is that when using postman, you're using dog1 as the name of this parameter. Change it to file to match the expected parameter name for the multipart file.
This approach worked for me.
The error in postman says
Required MultipartFile parameter 'file' is not present
The method signature looks fine defining file parameter:
ResponseEntity<?> writeUserProfilePhoto(
#PathVariable Long user, #RequestPart("file") MultipartFile file)
throws Throwable
The issue is that when using postman, you're using dog1 as the name of this parameter. Change it to file to match the expected parameter name for the multipart file.
#Override
public Response uploadImage(String token, MultipartFile file) {
long id=tokenUtil.decodeToken(token);
Optional<User> user=userRepo.findById(id);
if(!user.isPresent()) {
throw new UserException(-5, "User does not exists");
}
UUID uuid=UUID.randomUUID();
String uniqueUserId=uuid.toString();
try {
Files.copy(file.getInputStream(), fileLocation.resolve(uniqueUserId), StandardCopyOption.REPLACE_EXISTING);
user.get().setProfilePic(uniqueUserId);
userRepo.save(user.get());
}catch (IOException e) {
e.printStackTrace();
// TODO: handle exception
}
return ResponseHelper.statusResponse(200, "Profile Pic Uploaded Successfully");
}

Resources