krishna Ram
krishna Ram

Reputation: 659

Missing content for multipart request in Spring 4.0 MVC with Spring Security while File Upload

I am using Spring Security 4. I am getting error while multipart file upload.

Caused by: java.io.IOException: Missing content for multipart request
    at org.eclipse.jetty.util.MultiPartInputStream.parse(MultiPartInputStream.java:501)

In application config I have.

@Bean(name = "filterMultipartResolver")
     public CommonsMultipartResolver commonsMultipartResolver(){
         CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
         commonsMultipartResolver.setDefaultEncoding("utf-8");
         commonsMultipartResolver.setMaxUploadSize(50000000);
         return commonsMultipartResolver;
     }

In webserver config

ServletRegistration.Dynamic registration = servletCon.addServlet("dispatcher", new DispatcherServlet(servletConfig));
        registration.setLoadOnStartup(1);
        //it recognizes every url starting with / in localhost
        registration.addMapping("/");
        registration.setMultipartConfig(new MultipartConfigElement("/tmp", 1024*1024*5, 1024*1024*5*5, 1024*1024));

In AbstractSecurityWebApplicationInitializer

@Configuration
public class SecurityWebApplicationIntializer extends AbstractSecurityWebApplicationInitializer {
    @Override
      protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
        insertFilters(servletContext, new MultipartFilter());
      }
}

As I found in Stack overflow here, I removed Commons File Upload. It is making MultipartResolver Unavailable.

java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?

Please give some info on using MultiPart file with Spring Security.

This is my JSP file

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
    <meta name="_csrf" content="${_csrf.token}"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" content="${_csrf.headerName}"/>

 <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>
 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
</head>
<body ng-app='fileUpload'  ng-controller='UploadController'>
    <form enctype="multipart/form-data"
        ng-submit="submitForm()">
        File to upload: <input type="file" file-model="picBlob"><br /> Name: <input
            type="text" name="name" ng-model="result.success"><br /> <br /> <input type="submit"
            value="Upload"> Press here to upload the file!
            <input type="hidden" id="csrf" name="${_csrf.parameterName}" value="${_csrf.token}"  />
    </form>
    <script type="text/javascript">
    var tms = angular.module('fileUpload', []);

     tms.controller('UploadController', ['$scope', '$window','$http','fileUpload', function($scope, $window,$http,fileUpload) {
         $scope.result = {};
         var token = $("meta[name='_csrf']").attr("content");
          var header = $("meta[name='_csrf_header']").attr("content");
         $scope.submitForm = function(){

             var pic = $scope.picBlob;
             var uploadUrl = "/upload?_csrf="+token
             console.log(pic);
             fileUpload.uploadFileToUrl($scope.result,$scope.picBlob, uploadUrl);

         };

     }]);
     tms.directive('fileModel', ['$parse', function ($parse) {
            return {
                restrict: 'A',
                link: function(scope, element, attrs) {
                    var model = $parse(attrs.fileModel);
                    var modelSetter = model.assign;
                    element.bind('change', function(){
                        scope.$apply(function(){
                            modelSetter(scope, element[0].files[0]);
                        });
                    });
                }
            };
        }]);
     tms.service('fileUpload', ['$http', function ($http) {
            this.uploadFileToUrl = function(memberJson,file, uploadUrl){
                var fd = new FormData();
                fd.append('file', file);
                fd.append('properties', new Blob([JSON.stringify(memberJson)], {
                    type: "application/json"
                }));
                console.log(fd);
                $http.post(uploadUrl, fd, {
                    transformRequest: angular.identity,
                    headers: {'Content-Type': undefined}
                })
                .success(function(){
                })
                .error(function(){
                });
            }
        }]);

    </script>
</body>
</html>

This is my controller

package com.mindfiresolutions.springmaven.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.mindfiresolutions.springmaven.models.Result;

@Controller
public class FileUploadController {

    @RequestMapping(value="/upload", method=RequestMethod.GET)
    public @ResponseBody Result provideUploadInfo() {
        Result res = new Result();
        res.setError("You can upload a file by posting to this same URL.");
        return res;
    }

    @RequestMapping(value="/upload", method=RequestMethod.POST, consumes = {"multipart/form-data"})
    public @ResponseBody Result handleFileUpload( @RequestPart("properties") Result res,
            @RequestParam("file") MultipartFile file){
        Result result = new Result();
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                BufferedOutputStream stream =
                        new BufferedOutputStream(new FileOutputStream(new File("/tmp/new.txt")));
                stream.write(bytes);
                stream.close();
                result.setSuccess("You successfully uploaded " + res.getSuccess() + "!");
                return result;
            } catch (Exception e) {
                result.setError("You failed to upload " + res.getSuccess() + " => " + e.getMessage());
                return result;
            }
        } else {
            result.setError("You failed to upload " + res.getSuccess() + " because the file was empty.");
            return result;
        }
    }

}

Upvotes: 0

Views: 3471

Answers (1)

krishna Ram
krishna Ram

Reputation: 659

I got solution. Tweaked in Controller

@RequestMapping(value="/upload", method=RequestMethod.POST, consumes = {"multipart/form-data"})
    public @ResponseBody Result handleFileUpload( Result res,
            @RequestParam("file") MultipartFile file){
        Result result = new Result();
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                BufferedOutputStream stream =
                        new BufferedOutputStream(new FileOutputStream(new File("/tmp/new.txt")));
                stream.write(bytes);
                stream.close();
                result.setSuccess("You successfully uploaded " + res.getSuccess() + "!");
                return result;
            } catch (Exception e) {
                result.setError("You failed to upload " + res.getSuccess() + " => " + e.getMessage());
                return result;
            }
        } else {
            result.setError("You failed to upload " + res.getSuccess() + " because the file was empty.");
            return result;
        }
    }

Spring recognizes the object and Spring will cleanly bind your request parameters to your class instance. It was explicitly look for Object which was not getting.

Reference:here

Upvotes: 1

Related Questions