Spring Boot multipart upload getting null file obj

2019-05-04 22:29发布

问题:

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.

  • If it could upload, it would upload fine for the rest of the time.
  • If not, it won't work until I restart the server(likely more than one time)

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.

  1. Using StandardServletMultipartResolver.

    @Bean(name = "multipartResolver")
    public StandardServletMultipartResolver resolver() {
        return new StandardServletMultipartResolver();
    }
    
  2. 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;
    }
    
  3. 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.

回答1:

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.