Exemple de téléchargement de fichier MVC Spring

Exemple de téléchargement de fichier Spring MVC

Spring utilise l'interface deMultipartResolverpour gérer les téléchargements de fichiers dans l'application Web, deux des implémentations:

  1. StandardServletMultipartResolver - Analyse des requêtes en plusieurs parties du servlet 3.0.

  2. CommonsMultipartResolver - Common commons-fileupload.jar

Outils utilisés dans cet article:

  1. Spring 4.3.5.RELEASE

  2. Maven 3

  3. Tomcat 7 ou 8, Jetty 9 ou tout conteneur Servlet 3.0

En bref, cet article vous montre comment gérer le téléchargement de fichiers dans l'application Web Spring MVC, et comment gérer l'exception populaire de taille de fichier dépassée.

Note
Cet article se concentrera sur l'analyse des requêtes en plusieurs parties Servlet 3.0.

P.S Article is updated from Spring 2.5.x to Spring 4.3.x

1. Structure du projet

Une structure de projet Maven standard.

spring-mvc-file-upload-example-directory

2. Dépendance du projet

Dépendances Spring standard, pas besoin de bibliothèque supplémentaire pour le téléchargement de fichiers.

pom.xml


    4.0.0
    com.example
    spring-mvc-file-upload
    war
    1.0-SNAPSHOT
    Spring MVC file upload

    
        1.8
        4.3.5.RELEASE
        1.2
        3.1.0
        1.1.3
        1.7.12
    

    

        
            org.springframework
            spring-webmvc
            ${spring.version}
            
                
                    commons-logging
                    commons-logging
                
            
        

        
            javax.servlet
            jstl
            ${jstl.version}
        

        
        
            javax.servlet
            javax.servlet-api
            ${servletapi.version}
            provided
        

        
        
            org.slf4j
            jcl-over-slf4j
            ${jcl.slf4j.version}
        

        
            ch.qos.logback
            logback-classic
            ${logback.version}
        

    

    
        

            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.3
                
                    ${jdk.version}
                    ${jdk.version}
                
            

            
            
                org.eclipse.jetty
                jetty-maven-plugin
                9.2.11.v20150529
                
                    10
                    
                        /spring4upload
                    
                
            

            
            
                org.apache.maven.plugins
                maven-eclipse-plugin
                2.9
                
                    true
                    true
                    2.0
                    /spring4upload
                
            

        
    

3. MultipartConfigElement

Créez une classe d'initialisation de servlet et enregistrez unjavax.servlet.MultipartConfigElement

MyWebInitializer.java

package com.example;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration;
import java.io.File;

public class MyWebInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    private int maxUploadSizeInMb = 5 * 1024 * 1024; // 5 MB

    @Override
    protected Class[] getServletConfigClasses() {
        return new Class[]{SpringWebMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected Class[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {

        // upload temp file will put here
        File uploadDirectory = new File(System.getProperty("java.io.tmpdir"));

        // register a MultipartConfigElement
        MultipartConfigElement multipartConfigElement =
                new MultipartConfigElement(uploadDirectory.getAbsolutePath(),
                        maxUploadSizeInMb, maxUploadSizeInMb * 2, maxUploadSizeInMb / 2);

        registration.setMultipartConfig(multipartConfigElement);

    }

}

Vérifiez la signature de la méthodeMultipartConfigElement.

public MultipartConfigElement(java.lang.String location,
                              long maxFileSize,
                              long maxRequestSize,
                              int fileSizeThreshold)

4. Configuration du ressort

Enregistrez un beanmultipartResolver et renvoieStandardServletMultipartResolver

SpringWebMvcConfig.java

package com.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan({"com.example"})
public class SpringWebMvcConfig extends WebMvcConfigurerAdapter {

    // Bean name must be "multipartResolver", by default Spring uses method name as bean name.
    @Bean
    public MultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }

    /*
    // if the method name is different, you must define the bean name manually like this :
    @Bean(name = "multipartResolver")
    public MultipartResolver createMultipartResolver() {
        return new StandardServletMultipartResolver();
    }*/

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

}

À ce stade, l'analyse des requêtes en plusieurs parties de Servlet 3.0 est correctement configurée et vous pouvez commencer à télécharger le fichier.

4. Téléchargement d'un seul fichier

4.1 Normal HTML form tag.

upload.jsp




Spring MVC file upload example


4.2 Another page to show the upload status.

uploadStatus.jsp



Upload Status

Message : ${message}

4.3 In the Controller, map the uploaded file to MultipartFile

UploadController.java

package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.StringJoiner;

@Controller
public class UploadController {

    //Save the uploaded file to this folder
    private static String UPLOADED_FOLDER = "F://temp//";

    @GetMapping("/")
    public String index() {
        return "upload";
    }

    //@RequestMapping(value = "/upload", method = RequestMethod.POST)
    @PostMapping("/upload") // //new annotation since 4.3
    public String singleFileUpload(@RequestParam("file") MultipartFile file,
                                   RedirectAttributes redirectAttributes) {

        if (file.isEmpty()) {
            redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
            return "redirect:uploadStatus";
        }

        try {

            // Get the file and save it somewhere
            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);

            redirectAttributes.addFlashAttribute("message",
                        "You successfully uploaded '" + file.getOriginalFilename() + "'");

        } catch (IOException e) {
            e.printStackTrace();
        }

        return "redirect:/uploadStatus";
    }

    @GetMapping("/uploadStatus")
    public String uploadStatus() {
        return "uploadStatus";
    }

}

5. Téléchargement de fichiers multiples

5.1 Just add more file input.

uploadMulti.jsp




Spring MVC multi files upload example




5.2 In Spring Controller, maps the multiple uploaded files to MultipartFile []

UploadController.java

    //...

    @PostMapping("/uploadMulti")
    public String multiFileUpload(@RequestParam("files") MultipartFile[] files,
                                  RedirectAttributes redirectAttributes) {

        StringJoiner sj = new StringJoiner(" , ");

        for (MultipartFile file : files) {

            if (file.isEmpty()) {
                continue; //next pls
            }

            try {

                byte[] bytes = file.getBytes();
                Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
                Files.write(path, bytes);

                sj.add(file.getOriginalFilename());

            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        String uploadedFileName = sj.toString();
        if (StringUtils.isEmpty(uploadedFileName)) {
            redirectAttributes.addFlashAttribute("message",
                        "Please select a file to upload");
        } else {
            redirectAttributes.addFlashAttribute("message",
                        "You successfully uploaded '" + uploadedFileName + "'");
        }

        return "redirect:/uploadStatus";

    }

    @GetMapping("/uploadMultiPage")
    public String uploadMultiPage() {
        return "uploadMulti";
    }
    //...

6. Gérer la taille de téléchargement maximale dépassée

Pour gérer l'exception courante de dépassement de la taille maximale de téléchargement, déclare un@ControllerAdvice et intercepte lesMultipartException

GlobalExceptionHandler.java

package com.example.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MultipartException.class)
    public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) {

        redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
        return "redirect:/uploadStatus";

    }

    // For commons-fileupload solution
    /*@ExceptionHandler(MaxUploadSizeExceededException.class)
    public String handleError2(MaxUploadSizeExceededException e, RedirectAttributes redirectAttributes) {

        redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
        return "redirect:/uploadStatus";

    }*/
}

Tomcat Connection Reset
Si vous avez déployé sur Tomcat et que vous ne pouvez pas détecter l'exception de dépassement de la taille du fichier, cela peut être dû au paramètre TomcatmaxSwallowSize. Lire ceci -Spring file upload and connection reset issue

7. DEMO

Obtenez le code source ci-dessous et testez avec le serveur Jetty intégrémvn jetty:run.

7.1 Review the pom.xml above, the embedded Jetty will deploy the web application on this /spring4upload context.

Terminal

project $ mvn jetty:run
//...
[INFO] Started o.e.j.m.p.JettyWebAppContext@341672e{/spring4upload,
    file:/SpringMVCUploadExample/src/main/webapp/,AVAILABLE}{file:/SpringMVCUploadExample/src/main/webapp/}
[WARNING] !RequestLog
[INFO] Started ServerConnector@3ba1308d{HTTP/1.1}{0.0.0.0:8080}
[INFO] Started @3743ms
[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 10 seconds.

spring-mvc-file-upload-example1

7.3 Select a file ‘MyFirstExcel.xml‘ and upload it.

spring-mvc-file-upload-example2

spring-mvc-file-upload-example3

7.5 Select few files and upload it.

spring-mvc-file-upload-example4

7.6 Select a file larger than 5mb, you will visit this page.

spring-mvc-file-upload-max-size-exceed

8. Télécharger le code source

Télécharger -spring-mvc-file-upload-example.zip (10 KB)

P.S For Spring 2.5.x, try this Spring.2.5-file-upload-example.zip (10KB)