Spring Boot + Multipart文件上传产生格式错误的多部分请求

时间:2015-09-29 13:25:09

标签: spring spring-boot

我目前正在运行Spring Boot v1.3.0.BUILD-SNAPSHOT和Spring v4.2.2.BUILD-SNAPSHOT。

如果我尝试执行多文件上传(通过角度):

myService.upload = function(name ,content) {
    var fd = new FormData();
    fd.append('name', name);
    fd.append('file', content);   

    return $http({
      method: 'POST',
      url: SERVER_BASE_URL + 'upload',
      data: fd,
      transformRequest: angular.identity,
      headers: {
        'Content-Type': 'multipart/form-data'
      }}).then(function(res) {       
        return res.headers('Location');
      }, function(reason) {
          throw reason;
      });
};

我收到错误:

  

[WARN] org.eclipse.jetty.server.Request -    java.io.IOException:缺少初始多部分边界       at org.eclipse.jetty.util.MultiPartInputStreamParser.parse(MultiPartInputStreamParser.java:507)〜[jetty-util-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.util.MultiPartInputStreamParser.getParts(MultiPartInputStreamParser.java:400)〜[jetty-util-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.server.Request.getParts(Request.java:2139)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.server.Request.extractMultipartParameters(Request.java:385)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.server.Request.extractContentParameters(Request.java:308)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.server.Request.extractParameters(Request.java:256)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.Request.getParameter(Request.java:825)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70)[spring-web-4.2.2.BUILD-SNAPSHOT.jar:4.2.2.BUILD-SNAPSHOT]       在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)[spring-web-4.2.2.BUILD-SNAPSHOT.jar:4.2.2.BUILD-SNAPSHOT]       在org.eclipse.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1652)[jetty-servlet-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)[spring-web-4.2.2.BUILD-SNAPSHOT.jar:4.2.2.BUILD-SNAPSHOT]       在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)[spring-web-4.2.2.BUILD-SNAPSHOT.jar:4.2.2.BUILD-SNAPSHOT]       在org.eclipse.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1652)[jetty-servlet-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.ja [jetty-servlet-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)[jetty-security-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)[jetty-servlet-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.Server.handle(Server.java:499)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)[jetty-server-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.io.AbstractConnection $ 2.run(AbstractConnection.java:540)[jetty-io-9.2.13.v20150730.jar:9.2.13.v20150730]       at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)[jetty-util-9.2.13.v20150730.jar:9.2.13.v20150730]       在org.eclipse.jetty.util.thread.QueuedThreadPool $ 3.run(QueuedThreadPool.java:555)[jetty-util-9.2.13.v20150730.jar:9.2.13.30] 1507       在java.lang.Thread.run(Thread.java:745)[na:1.8.0_45]

我添加了一个多部分解析器bean:

@Bean
public FilterRegistrationBean openEntityManagerFilterRegistrationBean() {
    // Set upload filter
    final MultipartFilter multipartFilter = new MultipartFilter();
    final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(multipartFilter);
    filterRegistrationBean.addInitParameter("multipartResolverBeanName", "commonsMultipartResolver");

    return filterRegistrationBean;
}

@Bean
public CommonsMultipartResolver commonsMultipartResolver() {
    final CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
    commonsMultipartResolver.setMaxUploadSize(-1);

    return commonsMultipartResolver;
}

然而,看来hiddenHttpMethodFilter仍在我的多部分解析器之前被调用:

  

[DEBUG] org.eclipse.jetty.servlet.ServletHandler - 调用过滤器characterEncodingFilter   [DEBUG] org.eclipse.jetty.servlet.ServletHandler - 调用过滤器hiddenHttpMethodFilter   [WARN] org.eclipse.jetty.util.MultiPartInputStreamParser - 格式错误的多部分请求

我尝试将@Order(0)添加到我的Bean中,但这没有效果。

我还缺少什么?

2 个答案:

答案 0 :(得分:2)

我不使用过滤器上传文件。

在此尝试此方法:

{
    "size" : 1000,
    "query" : {
        "bool" : {
            "must" : [{
                    "match" : {
                        "field1" :  "this/is/a/url/test"                            
                    }
                }
            ]
        }
    }
}

// in configs
  @Bean
     Public MultipartConfigElement multipartConfigElement () {
         End MultipartConfigFactory factory = new MultipartConfigFactory ();
         Factory.setMaxFileSize ( "50MB");
         Factory.setMaxRequestSize ( "50MB");
         Return factory.createMultipartConfig ();
     }

注意:请记住删除放在配置中的过滤器

我希望能帮助

答案 1 :(得分:0)

这只是意味着您的角度js代码存在问题。 您将不得不在浏览器上进行调试,确切地发送了什么,并且肯定会丢失标题。使用像firebug这样的工具。试试这段代码。

pd.DataFrame(dict(zip(list1, list2)))

#   1   2   3
#0  1   2   3
#1  1   2   3
#2  1   2   3

绝对必要的是配置对象的以下两个属性:

var fd = new FormData();
fd.append('file', file);
fd.append('data', 'string');
$http.post(uploadUrl, fd, {
   transformRequest: angular.identity,
   headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});

覆盖Angular的默认序列化,保留我们的数据。

transformRequest: angular.identity

让浏览器将正确的Content-Type检测为multipart / form-data,并填入正确的边界。