Reputation: 151
I am getting a problem while implementing multipart file upload using spring boot 1.5.2.
Here is the situation, I have a mapping to handle file upload process.While I start the spring server, it starts without any error. The problem is that I would either able to upload the file perfectly fine or I would get null on all attribute in FileBucket object.
This situation would stay forever if I do not shutdown the server.
Here is the mapping.
@RequestMapping(value = {"/api/upload"}, method = RequestMethod.POST)
public ResponseEntity<Map<String, Integer>> upload(@Valid FileBucket fileBucket, BindingResult result) throws IOException {
Session session = sessionFactory.openSession();
User user = (User) session.load(User.class, getUserId());
Map<String, Integer> model = new HashMap<String, Integer>();
if (result.hasErrors()) {
System.out.println("validation errors");
System.out.println(result);
session.close();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
} else {
int documentId = saveDocument(fileBucket, user);
model.put("documentId", documentId);
session.close();
return new ResponseEntity<Map<String, Integer>>(model, HttpStatus.OK);
}
}
And the FileBucket
object
public class FileBucketConversation {
private MultipartFile file;
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file = file;
}
}
I have tried few ways to implement file upload, and still having the same situation.
Using StandardServletMultipartResolver
.
@Bean(name = "multipartResolver")
public StandardServletMultipartResolver resolver() {
return new StandardServletMultipartResolver();
}
Using CommonsMultipartResolver
v1.3.2.
@Bean(name="multipartResolver")
public CommonsMultipartResolver multipartResolver () {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(MAX_FILE_SIZE);
return resolver;
}
overriding MultipartFilter
@Bean
@Order(0)
public MultipartFilter multipartFile() {
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}
Enable spring.http.multipart
in properties file
spring.http.multipart.enabled=true
spring.http.multipart.max-file-size=20Mb
spring.http.multipart.max-request-size=20Mb
I really have no clue where to start looking. The problem happen occasionally, it do not happen every time I start the server but most of the time. Hoping some one could help me.
Thank you.
Upvotes: 5
Views: 11915
Reputation: 576
Update for Spring Boot 2 and Spring 5
spring.http.multipart.enabled
is deprecated, so forget about it.
Registering my own beans for MultipartConfigElement
or MultipartResolver
broke it for me.
I ended up with a @PostMapping
method with a single parameter, @RequestPart(name = "file") MultipartFile file
. Adding a parameter @RequestHeader HttpHeader headers
helped me make sure the client was sending the required header Content-Type with a boundary.
I'm using a Node client with the form-data library and node-fetch. Here's the client code:
const formData = new FormData();
const fileMetadata = {filename: fileName, contentType: 'image/png', knownLength: fs.statSync(pathToFile)};
const formData.append('file', fs.createReadStream(pathToFile), fileMetadata);
fetch(url, {method: 'POST', body: formData});
Upvotes: 1
Reputation: 4412
I had the same problem, this is my solution:
In application.yml:
spring:
http:
multipart:
enabled: false
In configuration:
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
...
@Bean
public MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
In RestController:
@PostMapping(value = "api/upload", consumes = "multipart/form-data")
public void enablePurchase(@RequestHeader HttpHeaders headers,
FileBucketConversation fileBucketConversation) {
...
}
Important: In your client don't use any header to define the Content-type or boundary. I'm using Angular 4 and when I remove these headers from my code it works (I only set the User token):
/* DON'T USE THIS:
let boundary = "ABDCE";
headers.append("Content-type", "multipart/form-data;boundary=" + boundary);
headers.append("enctype", "multipart/form-data;boundary=" + boundary);
headers.append("boundary", boundary);
*/
I hope this help you.
Upvotes: 4