ssm framework (based on annotation) MultipartFile object is null

Code:

This is my backend code
 @ResponseBody
    @RequestMapping("/uploadImg")
    public Object testUp(MultipartFile pimage,HttpSession session) throws IOException{
        //Get the file name of the uploaded file
        String filename = pimage.getOriginalFilename();
        //Get the suffix name of the deleted file
        String suffixName = filename.substring(filename.lastIndexOf("."));
        //Use UUID as file name
        String uuid = UUID.randomUUID().toString();
        filename = uuid + suffixName;
        //Get the path to the photo directory in the server through ServletContext
        ServletContext servletContext = session.getServletContext();
        String photoPath = servletContext.getRealPath("photo");
        File file = new File(photoPath);
        if (!file.exists()){
            file.mkdir();
        }
        String finalPath = photoPath + File.separator + filename;
        pimage.transferTo(new File(finalPath));

        System.out.println(finalPath);

        //In order to display the image on the client, the stored file name needs to be passed back. Since it is a custom upload plug-in, JSON needs to be processed manually here.
        JSONObject object = new JSONObject();
        object.put("imgurl",filename);
        //Remember: JSON objects must be returned to the client via toString()

        return object.toString();
    }

The front end uses the ajaxFileUpload plug-in to upload. What I want to do is to upload files through ajax, how to return the name of the file, and finally perform url splicing to echo the uploaded image.

<script th:inline="javascript">
  let url = [[${#servletContext.contextPath}]];

  function fileChange() {//Note: The change event in jQuery cannot be used here, so it is only triggered once, so use the :onchange attribute of the label
    alert("change");
    $.ajaxFileUpload({
      url: url + '/product/uploadImg',//server-side request address for file upload
      secureuri: false,//Generally set to false
      fileElementId: 'pimage',//The id attribute of the file upload control <input type="file" id="pimage" name="pimage" />
      dataType: 'json',//The return value type is generally set to json
      success: function (obj) //Server successful response processing function
      {
        alert(obj);
        $("#imgDiv").empty(); //Clear the original data
        //Create img tag object
        var imgObj = $("<img>");
        //Add attributes to the img tag object
        imgObj.attr("th:src", "/photo/" + obj.imgurl);
        imgObj.attr("width", "100px");
        imgObj.attr("height", "100px");
        //Append the image img tag to the end of imgDiv
        $("#imgDiv").append(imgObj);
        //Assign the name of the image (obtained from the JSON returned by the server) to the file box
        //$("#imgName").html(data.imgName);
      },
      error: function (e)//server response failure processing function
      {
        alert(e.message);
      }
    });
  }
</script>

html fragment, if there are too many others, the fragment is cut off, and the thymeleaf view parser is used.

<form th:action="@{/product/uploadImg}" method="post" enctype="multipart/form-data">
  Avatar: <input type="file" id="pimage" name="pimage" onchange="fileChange()">

  <input type="submit" value="Upload">
  <br><br><br><br>

  <div id="imgDiv" style="display:block; width: 40px; height: 50px;"></div>

</form>

Question:

NullPointerException NullPointerException

java.lang.NullPointerException
mvc.controller.ProductInfoController.testUp(ProductInfoController.java:70)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

log:
18:51:06.092 [http-nio-8080-exec-74] DEBUG org.springframework.web.servlet.DispatcherServlet - POST "/mi/product/uploadImg", parameters={}
18:51:06.092 [http-nio-8080-exec-74] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to mvc.controller.ProductInfoController#testUp(MultipartFile, HttpSession)
18:51:06.107 [http-nio-8080-exec-74] DEBUG org.springframework.web.servlet.DispatcherServlet - Failed to complete request: java.lang.NullPointerException

Appears in this line of code

String filename = pimage.getOriginalFilename();

Through debugging, it was found that the <strong>pimage </strong> object was null, so an exception was reported. I searched online for a long time to find dependencies and configurations. . . None of them have any effect, and a null pointer exception is always reported.

CommonsMultipartResolver

is also configured in the springMVCConfig configuration class.

@Bean
    public CommonsMultipartResolver getCommonsMultipartResolver(){
        return new CommonsMultipartResolver();
    }
No effect either

Because it is based on the annotation method, I searched for the problem all day, and finally found it for me. It is indeed the unmatched location of CommonsMultipartResolver.

Annotation-based web configuration class

Correct configuration location:

public class Web extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     * Spring configuration class
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    /**
     * SpringMVC configuration class
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMVCConfig.class};
    }

    /**
     * DispatcherServlet intercepts all paths
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    /**
     * filter
     * @return
     */
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceResponseEncoding(true);

        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
    }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        //File Upload
        registration.setMultipartConfig(
                new MultipartConfigElement("",1024*1024*500,1024*1024*500,0)
        );
    }

}

That is, the bottom one Rewrite the customizeRegistration method, so that the configuration is correct! !

Based on xml configuration

If it is based on xml, just add the CommonsMultipartResolver bean directly to SpringMVC.xml.

<!--The file must be parsed by the file parser to convert the file into a MultipartFile object-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>