Spring RestController submit file - java

As a part of a client request - image file must be submitted to my Spring RestController endpoint.
Is it possible to use #RequestParam("file") MultipartFile file with RestController ?
If so, could you please show an example.

Yes, it is possible and quite simple:
#RequestMapping("upload")
public void upload(#RequestParam("file") MultipartFile file){
//Do what you like with the file
}

Related

Create a REST API to upload Multipart file data in spring boot

I have created a rest API to accept MULTIPART_FORM_DATA as below. But once I hit the service using Postman, I am getting HTTP Status 415 – Unsupported Media Type exception
#POST
#Path("/fileupload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public String uploadfile(#RequestParam(value = "file") MultipartFile file) {
System.out.println(file.getName());
return "Success String";
}
What is wrong here? To consume MediaType.MULTIPART_FORM_DATA, do I need to make any modifications?
In Postman I have attached a text file in the BODY and hit the endpoint. The content type is set as "multipart/form-data"
Seems like you are confused with Spring rest API with Rest easy implementation.
In Resteasy,
Normal way to handle uploaded file is via
MultipartFormDataInput or Map uploaded file to a
POJO class via #MultipartForm
https://www.mkyong.com/webservices/jax-rs/file-upload-example-in-resteasy/
How to POST a multipart/form data with files programatically in a REST API
If you want to use spring rest approach, refer here
Multipart File upload Spring Boot
Have a look on below tutorial on uploading file in spring boot
https://devkonline.com/tutorials/content/ANGULAR-8-SPRING-BOOT-FILE-UPLOAD
You have probably imported different annotations.
Try it this way
import org.springframework.web.bind.annotation.*;
import static org.springframework.http.MediaType.*;
#PostMapping(value = "/fileupload", consumes = MULTIPART_FORM_DATA_VALUE, produces = APPLICATION_JSON_VALUE)
public String uploadfile(#RequestParam(value = "file") MultipartFile file) {
System.out.println(file.getName());
return "Success String";
}

spring boot file upload on 1.5.9 always returns null file object

I am trying for file upload in spring boot i searched a lot of options in stackoveroverflow still it ends me with null file object
#RequestMapping(value="/fileUpload",method=RequestMethod.POST)
public #ResponseBody ResponseEntity<String> handleFileUpload(#ModelAttribute("file")MultipartFile file)
what's going wrong in this
I tried to upload yaml file with restClient/postman file as option without any header content/multipart data
Define a request parameter for your file and a MultiPartFile. Now you can post your file with Postman. In the body of your request define a key with the name "file" (your request parameter) and as the value select your file.
#PostMapping("fileUpload")
public void upload(#RequestParam("file") MultipartFile file) {
fileService.writeFile(file);
}

"The current request is not a multipart request" when trying to test with MockMvc without uploading any file

I want to test a RequestMapping which takes some information about an item and then persists it, it also allows for images to be uploaded. However, the image uploading is not mandatory and my HTML form is using: enctype="multipart/form-data". I am trying to test the controller without actually uploading any files, the controller looks like this:
#RequestMapping(value="/admin/upload", method=RequestMethod.POST)
public ModelAndView addItem(
#RequestParam(value="id", required=true) Integer id,
#RequestParam(value="name", required=true) String name,
#RequestParam(value="image", required=false) MultipartFile file,
) throws IOException {
// some stuff here
ModelAndView mov = new ModelAndView();
return mov;
}
Even though I've set the required flag to be false I am getting the issue of a missing parameter, but more importantly, is it possible to send headers in the mockMvc request which would allow me to test this mapping without the need for uploading any images?
mockMvc.perform(post("https://localhost/store-admin/items/itemAddSubmit")
.param("id", 1)
.param("name", "testname").with(csrf()))
.andDo(print());
For multipart request you need to use fileUpload method instead of get, post or whatever.
Update your code as follows -
mockMvc.perform(fileUpload("https://localhost/store-admin/items/itemAddSubmit")
.param("id", 1)
.param("name", "testname").with(csrf()))
.andDo(print());
To actually send a file use the file function with fileUpload as shown below -
mockMvc.perform(fileUpload("https://localhost/store-admin/items/itemAddSubmit")
.file(myMockMultipartFile)
.param("id", 1)
.param("name", "testname").with(csrf()))
.andDo(print());
where myMockMultipartFile is a MockMultipartFile object.
Very important to note - if the [#RequestParam that accepts the file] on your REST endpoint doesn't have a "value=" attribute set, it will also throw the same type of an error when running a mock test. You could have ignored the "value" attribute when running the solution in prod and not experienced any error, but doing so would prevent you from running a test and injecting in the file programmatically.
Ex:
#RequestParam(value="file") final MultipartFile file,
Your question already showed this properly, but I want to document this answer for users in the future who may, like myself, overlook such a small detail.
Cheers

Spring file upload content type validation, always octet-stream?

I'm trying to implement pdf file uploading in my Restful Spring Boot application.
I have the following method;
#RequestMapping(value = FILE_URL, method = RequestMethod.POST)
public ResponseDTO submitPDF(
#ModelAttribute("file") FileDTO file) {
MediaType mediaType = MediaType.parseMediaType(file.getFile().getContentType());
System.out.println(file.getFile().getContentType());
System.out.println(mediaType);
System.out.println(mediaType.getType());
if(!"application/pdf".equals(mediaType.getType())) {
throw new IllegalArgumentException("Incorrect file type, PDF required.");
}
... more code here ...
}
FileDTO is just a wrapper around MultipartFile.
I'm then using Postman to POST the request with form-data body 'file'=<filename.pdf>
The content type in the printlns above is ALWAYS octet-stream. No matter what type of file I send in (png, pdf, etc) its always octet stream. If I specifically set application/pdf as Content-Type header in Postman the MultipartFile within FileDTO ends up as null.
Question is, is there something wrong with my Spring Controller method, or is the request just not being built correctly by Postman?
If Postman can't get the Content-Type right, can I expect actual client apps to properly set content type to pdf?
Have you tried Apache Tika library for detecting mime types of uploaded file?
Code Example in Kotlin
private fun getMimeType(file: File) = Tika().detect(file)
The FileDTO will wrap the whole content of the multipart/form-data so if your uploaded file input is named file, your DTO/Form/POJO should be alike to:
class FileDTO{
#NotNull
private String anotherAttribute;
#NotNull
private MultipartFile file;
//Getters and Setters
}
Therefore you should also change your controller function to
#RequestMapping(value = FILE_URL, method = RequestMethod.POST)
public ResponseDTO submitPDF(#ModelAttribute FileDTO fileWrapper) {
MediaType mediaType = MediaType.parseMediaType(fileWrapper.getFile().getContentType());
System.out.println(fileWrapper.getFile().getContentType());
System.out.println(mediaType);
System.out.println(mediaType.getType());
if(!"application/pdf".equals(mediaType.getType())) {
throw new IllegalArgumentException("Incorrect file type, PDF required.");
}
... more code here ...
}
To use this sort of functions you should use the StandardServletMultipartResolver in your MVC configurer file. Something like:
#EnableWebMvc
#Configuration
#ComponentScan("mypackage.web.etc")
public class WebMvcConfig extends WebMvcConfigurerAdapter{
#Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
}
I hope it suites you.
Normally file uploads are wrapped in a MIME multipart message format, so the content type in the HTTP header can only be multipart/form-data and you specify the MIME type of each field (include files) separately in each part.
It seems in Postman there's no way to specify the MIME type for a multi-part field so I can only assume it's a missing feature.
I've had this issue before, using the following fixed the issue:
Files.probeContentType(path)
The above returns a string with the format type. Seems to be the most reliable solution I've tried.

How to add a file to upload in message flow of Mule ESB?

This is my Controller use SpringMVC, it has 2 params is "file" and "fileDesc":
#RequestMapping(value = "/uploadfiles", method = RequestMethod.POST)
#ResponseBody
public String createResource(#RequestParam("file") MultipartFile[] files, #RequestParam("fileDesc") String fileDesc, Locale locale)
throws IOException, ServiceProcessException {...}
And this is my design in Mule:
I don't know how to get files to get value in controller because data I send to Mule then point to Controler in runtime.
A similar use case has been discussed here.
HTH.

Categories