Issue with Tomcat and parsing MultipartFile Upload service - java

I have an app with an endpoint and a tomcat server running with it. I can hit an endpoint on postman with a file and have it uploaded to an excel file on my server.
The problem is in order to get it to work I have to add allowCasualMultipartParsing="true" in the context.xml of my tomcat I don't want to have to add this fix on my local tomcat.
I need a fix that will work despite the tomcat server it's running on. So if someone were to add a new tomcat they wouldn't have this issue. For example on tomcat 9.0.6
Its hard to demonstrate the issue because it's due to running the app on a standalone tomcat. It works when I run it without the standalone tomcat 9.0.38 .
Code for uploading file
#Controller
#RequestMapping("/ListCtrl")
public class listController {
#RequestMapping(method = {RequestMethod.POST}, value = "/list")
#Consumes (MediaType.MULTIPART_FORM_DATA)
#Produces (MediaType.TEXT_XML)
#ResponseBody public Map<String, Object> uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") MultipartFile file,
#RequestParam("listName") String listName,
#RequestParam Integer
listid){
Map<String, Object> resultMap = null;
resultMap = new HashMap<>();
resultMap.put("status", "successful");
resultMap.put("file", file.getName());
System.out.println(file.getOriginalFilename());
return resultMap;
}
The error I'm getting on the project that isn't working is
HTTP Status 500 - Could not parse multipart servlet request; nested exception is java. lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided

I found the solution. I've seen it before but didn't fully understand so I wanted to elaborate here in case anyone else sees it. This solution will work despite the tomcat its running on.
You need to create a META-INF folder. For me I created under a deployed resources folder and I added a context.xml. After I put allowCasualMultipartParsing="true" in the context tag.
Webapp/Deployed Resources/META-INF/context.xml.
Spark Java: Unable to process parts as no multi-part configuration has been provided

It is enough if you provide a configuration. As it has been mentioned in the spring documentation, there are two concrete implementations included in Spring.
CommonsMultipartResolver for Apache Commons FileUpload and
StandardServletMultipartResolver for the Servlet 3.0+ Part API
For better flexibility and configurabilities sake, I choose to use CommonsMultipartResolver. Among the advantages, it provides maxUploadSize, maxInMemorySize, and defaultEncoding settings as bean properties. But, you have to import it as:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
And in your code:
#Configuration
public class WebConfig {
private int maxUploadSizeInMb = 2 * 1024 * 1024; // 2 MB
...
...
#Bean("multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver cmr = new CommonsMultipartResolver();
cmr.setMaxUploadSize(maxUploadSizeInMb * 2); //sum size of all files/parts of a file. Since, a file may be partitioned
cmr.setMaxUploadSizePerFile(maxUploadSizeInMb);//maximum file size of each file
return cmr;
}
}

Related

Trying to download a .gz file using Spring Boot with API

I'm trying to download a .gz file from a NEXRAD (Next Generation Weather Radar) api with Spring Boot.
Here is the original link:
https://noaa-nexrad-level2.s3.amazonaws.com
And this is the link where the file gets downloaded automatically on hitting it:
https://noaa-nexrad-level2.s3.amazonaws.com/1991/06/05/KTLX/KTLX19910605_162126.gz
Here is the website which gives info about NEXRAD:
https://github.com/awslabs/open-data-docs/tree/main/docs/noaa/noaa-nexrad
I'm quite new to Spring Boot and I first tried hitting a random countries url and getting a json. Here is the code I wrote for it:
#RestController
public class ApiController {
#Autowired
private RestTemplate restTemplate;
private static String url = "https://restcountries.com/v3.1/all";
#GetMapping("/countries")
public List<Object> getCountries() {
Object[] countries = restTemplate.getForObject(url, Object[].class);
return Arrays.asList(countries);
}
This code works correctly where I'm able to get a json displayed on the browser on hitting the /countries url and appending it to localhost.
But now I want to hit the NEXRAD url and download the .gz file. Can anyone help on that?
You'll need a separate endpoint to download the file. Please have a look at the accepted answer to this question: download a file from Spring boot rest service

Spring Boot 2.0.2 MultipartConfigElement not being configured for MultipartFile

I'm using Spring Boot 2.0.2.RELEASE, and not being able to upload files for a REST controller endpoint.
Following this getting starter, it says:
As part of auto-configuring Spring MVC, Spring Boot will create a
MultipartConfigElement bean and make itself ready for file uploads.
So, theoretically, It should work without any additional configurations, but it looks like this MultipartConfigElement is not being configured at all.
I'm getting this warn:
WARN .a.w.r.e.DefaultErrorWebExceptionHandler: Failed to handle request [POST http://localhost:8080/upload]: Response status 400 with reason "Required MultipartFile parameter 'file' is not present"
My Spring application starter is as simple as:
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
And my endpoint is:
#RestController
public class MyController {
#PostMapping("/upload")
public String hash(#RequestParam("file") MultipartFile file) {
final String test = file.getContentType();
}
This is the way I'm sending with postman:
I also made sure to unmark any default content type set by postman, with no success.
What possibly am I doing wrong?
First, add this to your properties file
servlet.multipart.enabled=true
servlet.multipart.max-file-size=20M
And create CommonsMultipartResolver bean as
(name = "multipartResolver")
Same question,but I got these files by this way.
You can found these files in this github repository:
gs-uploading-files
All you need to do is just download the zip file of this application,and find the files you need.

Unexpected EOF read on the socket during file upload with Spring Boot 2.0

I am working on webapp, which is using Spring Boot 2.0 on back-end.
For some amount of users I am seeing this kind of error:
Failed to parse multipart servlet request; nested exception is
java.io.IOException:
org.apache.tomcat.util.http.fileupload.FileUploadBase
$IOFileUploadException: Processing of multipart/form-data request
failed. Unexpected EOF read on the socket]
org.springframework.web.multipart.MultipartException: Failed to parse
multipart servlet request; nested exception is java.io.IOException:
org.apache.tomcat.util.http.fileupload.FileUploadBase
$IOFileUploadException: Processing of multipart/form-data request
failed. Unexpected EOF read on the socket at
org.springframework.web.multipart.support.
StandardMultipartHttpServletRequest.
handleParseFailure(StandardMultipartHttpServletRequest.java:122) at
org.springframework.web.multipart.support.
StandardMultipartHttpServletRequest.
parseRequest(StandardMultipartHttpServletRequest.java:113) at
org.springframework.web.multipart.support.
StandardMultipartHttpServletRequest.<init
(StandardMultipartHttpServletRequest.java:86) at
org.springframework.web.multipart.support.
StandardServletMultipartResolver.
resolveMultipart(StandardServletMultipartResolver.java:93) at
org.springframework.web.servlet.DispatcherServlet.
checkMultipart(DispatcherServlet.java:1128) at
org.springframework.web.servlet.DispatcherServlet.
doDispatch(DispatcherServlet.java:960) at
org.springframework.web.servlet.DispatcherServlet.
doService(DispatcherServlet.java:925)...
Could you help me to understand the root of this problem. I am using this code on server, which looks fine:
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity<String> upload(HttpSession session,
MultipartHttpServletRequest request) {
MultipartFile multipartFile = request.getFiles("file");
try (InputStream inputStream = multipartFile.getInputStream()) {
//logic ...
}
}
As I see from logs, request even don't call server endpoint and fails during sending data from UI side. Looks like some network problem?
Another strange thing is that this kind of error happens like random. Just for ~2-4% jof users requests. Even if user that had problem with upload tries to upload a few more times, often it works fine after that
Thanks for any answers!
I experince the same problem with a Spring Boot 1.5.14.RELEASE.
I managed to reproduce the problem by using a custom throtlling (20KB/s) mode on Chrome. When I upload a big picture (8MB) I get a timeout after 30 seconds.
Please note that I am doing the upload via ajax using Dropbox.
I investigated a bit and I saw that the Tomcat Connector has a default value for async requests timeout:
/**
* Default timeout for asynchronous requests (ms).
*/
protected long asyncTimeout = 30000;
I tried to increment this limit using the property that Spring Boot provides:
# SPRING MVC (WebMvcProperties)
spring.mvc.async.request-timeout= # Amount of time before asynchronous request handling times out.
Unfortunately, in my case that did not work. So I tried to configure the timeout programatically:
#Configuration
public class ServerConfiguration {
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
#Override
public void customize(Connector connector) {
connector.setAsyncTimeout(60000);
connector.getExecutorName();
}
});
return factory;
}
}
That did not work, but I'm pretty sure that is the problem. I saw other people that configured the Connector timeout this way and it worked for them...
I still have no idea why in my case the default value is still being used.
Try it and tell me how it went please.
Update
I figured out what was happening. It turns out that Dropzone had a timeout itself.
https://www.dropzonejs.com/#config-timeout
I set that to the value I wanted and everything worked fine.
Spring boot was setting the value of the property:
spring.mvc.async.request-timeout= # Amount of time before asynchronous request handling times out.
perfectly.

How to limit size of multipart file in a java controller

I have a rest controller method that receive a multipart file parameter, I need to constraint the file size limit of it. I tried different optiones but it's not working yet for me. I´m using Apache Tomcat 8. I'm calling the rest method by a windows service.
Following the definition of the class and the method:
#Controller
public class MyClass{
...
}
#RequestMapping(value = "/path/method/param1/{param1}/param2/{param2}/",
method = RequestMethod.POST)
public ResponseEntity<String> method(DTO dto, #RequestParam("file") MultipartFile multipartFile){
...
}
Solutions tested:
Adding the following node in the web.xml file
<multipart-config>
<max-file-size>52428800</max-file-size>
<max-request-size>52428800</max-request-size>
<file-size-threshold>0<</file-size-threshold>
</multipart-config>
Adding maxPostSize and maxSwallowSize properties to the connector node in the server.xml file
Adding parameters of size to the .properties file
Adding the #MultipartConfig annotation in the controller class
Any idea or suggestions?
Check the spring-servlet.xml file, maybe there is a created bean of the class org.springframework.web.multipart.commons.CommonsMultipartResolver, it could be above of the rest of configurations or methods to handle this

Avoid file extension detection in Spring MVC request mapping with floating point number in URI

I used Spring Boot to implement a REST application. I have one resource that is mapped like this
#RequestMapping(value = "/{fromLat}/{fromLon}/{toLat}/{toLon:.+}", method = {RequestMethod.GET},
produces = {"application/json"})
Thus the path contains coordinates and a request looks like this
$ curl -I -X GET http://localhost:8085/foobar/53.481297/9.900539/53.491691/9.946046
Unfortunatly the last end is interpreted as a file extension which leads to a response header that offers a file download instead of just the plain data.
Content-Disposition: attachment;filename=f.txt
I thought I could handle the situation with a custom WebMvcConfigurerAdapter Bean (and without #EnableWebMvc) annotation like explained here.
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
But that does not do the trick. Unfortunatly the detected file extension is not fix - thus I can not use a rule for a fix extension.
How can I configure the system to just respond with the content and without the Content-Disposition header (which leads to an f.txt download)? I would not like to use a slash ("/") at the end.
I already looked at the following ressource
Spring MVC controller browser downloads "f.txt"
Add property support for configureContentNegotiation
In Spring Framework 4.1.9 and 4.2.3 the Content-Disposition header was fixed to use the "inline" type which only suggests a file download name, should the content end up being downloaded. It won't force a Save As dialog any more.
Note also that the reason for the Content-Disposition header in the first place is to protect applications against RFD attacks. This is a very complex issue but you can see a summary in the CVE-2015-5211 report.
I had similar issues with Spring Boot as described here.
What worked for me is the following configuration:
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}
}
Did you try to set:
1) Content-Disposition: inline; -> you can use:
return new ResponseEntity(body, headers, statusCode); and set Content-Disposition in headers.
Look here:
How to set 'Content-Disposition' and 'Filename' when using FileSystemResource to force a file download file?
and
Return a stream with Spring MVC's ResponseEntity
2) text/x-json - Experimental MIME type for JSON before application/json got officially registered.
#RequestMapping(value = "/{fromLat}/{fromLon}/{toLat}/{toLon:.+}", method = {RequestMethod.GET},
produces = {"text/x-json"})
It will try to display the content instead of downloading it.
Hope it will help.

Categories

Resources