0

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;
        }
    }

}
Community
  • 1
  • 1
krishna Ram
  • 639
  • 3
  • 9
  • 20
  • Where is your controller mapping and your JSP/HTML from which you are uploading, they happen to be most important. Looks like you are somehow not sending any file as multipart file from front-end – We are Borg Dec 01 '15 at 16:36
  • I am sending it, If file is not sent it gives media type error. – krishna Ram Dec 01 '15 at 16:40
  • How are you sending it? That's what is there in JSP/HTML and where is your mapping? – We are Borg Dec 01 '15 at 16:42
  • Like this I am sending http://stackoverflow.com/questions/21329426/spring-mvc-multipart-request-with-json/25183266#25183266 – krishna Ram Dec 01 '15 at 16:46
  • You are a difficult person my friend, you are posting links from other peoples question but wont edit your own to add the controller & JS code, which the guy in your link has added. I guess I wont be able to help you. Good luck. – We are Borg Dec 01 '15 at 16:48
  • Sure I will add now. – krishna Ram Dec 01 '15 at 16:49
  • @WeareBorg I have added now, sorry. I must have added it before. – krishna Ram Dec 01 '15 at 16:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/96705/discussion-between-ramki-and-we-are-borg). – krishna Ram Dec 01 '15 at 17:04
  • I just came home, can we continue this discussion next morning, German time 10:30am. :-) Also our inhouse JS guy is there, I dont know JS, so I can ask him. – We are Borg Dec 01 '15 at 18:04
  • 1
    So, the friend says, the problem is with you trying to send out Blob. We also tried that thing, and it doesn't work. Why not just send from the JSP directly the Multipart file, without the usage of JS. – We are Borg Dec 02 '15 at 08:49
  • Hi, Thanks for helping. The project need is like that, I have to use angular with Spring. – krishna Ram Dec 02 '15 at 08:50

1 Answers1

1

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

Community
  • 1
  • 1
krishna Ram
  • 639
  • 3
  • 9
  • 20