代码之家  ›  专栏  ›  技术社区  ›  AdamC

内容长度标头已存在

  •  28
  • AdamC  · 技术社区  · 15 年前

    HttpClient client = new DefaultHttpClient();
    putMethod = new HttpPut(url + encodedFileName);
    putMethod.addHeader(..)  //<-once for each header
    putMethod.setEntity(new ByteArrayEntity(data));
    client.execute(putMethod);  //throws Exception
    

    原因:org.apache.http.ProtocolException:内容长度标头已存在

    有什么想法吗?

    6 回复  |  直到 15 年前
        1
  •  32
  •   Stephen C    15 年前

    我自己没有使用过HttpClient,但我怀疑问题是 putMethod.setEntity(...) putMethod.addHeader(...) 电话。

        2
  •  45
  •   John Rix    10 年前

    正如igor.zh所指出的,如果使用Spring的HttpComponentsMessageSender类,就会出现这个问题。更确切地说,如果您将自己的HttpClient实例传递到HttpComponentsMessageSender构造函数中,这只是一个问题,否则问题将自动处理。

    https://jira.spring.io/browse/SWS-835

    使用HttpClientBuilder.addInterceptorFirst方法将此拦截器注入到您自己的HttpClient实例中。下面的示例使用xmlbean连接。如果有人知道构造HttpClient实例的更简洁的方法(除了编写工厂bean类之外),我洗耳恭听!

    <bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"/>
    
    <bean id="interceptedHttpClientBuilder" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="httpClientBuilder" />
        <property name="targetMethod" value="addInterceptorFirst"> </property>
        <property name="arguments">
            <list>
                <bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender.RemoveSoapHeadersInterceptor"/>
            </list>
        </property>
    </bean>
    
    <bean id="httpClient" factory-bean="interceptedHttpClientBuilder" factory-method="build" />
    
    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <constructor-arg ref="messageFactory"/>
        <property name="messageSender">
            <bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
                <property name="httpClient" ref="httpClient"/>
            </bean>
        </property>
    </bean>
    

    或者,如果可以的话,只允许HttpComponentsMessageSender构造自己的HttpClient实例,而不是将一个实例传递给它。注意:从springws 2.2.0-RELEASE开始,HttpComponentsMessageSender的默认构造函数继续使用DefaultHttpClient类,该类现在已被弃用。希望在将来的版本中能够解决这个问题。

        3
  •  15
  •   igor.zh    11 年前

    当我使用 http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html 作为springwebservice消息发送者。在这种情况下,HttpPut或HttpRequest之类的内容不容易访问,因此,使用HttpClientBuilder构建HttpClient时,我最终在罪魁祸首RequestContent前面插入了一个HttpRequestInterceptor:

    private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{
        @Override
        public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
            request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present");
        }
    }
    ...
        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        httpClientBuilder.addInterceptorFirst(new CcontentLengthHeaderRemover());
    
        4
  •  7
  •   Muhd Marcin    8 年前

    John Rix's answer 有正确的想法。下面是使用纯java的方法:

    HttpClient client = HttpClients.custom()
        .addInterceptorFirst(new RemoveSoapHeadersInterceptor())
        .build();
    
        5
  •  1
  •   Prannay    14 年前

    http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html 您会注意到,如果您自己设置了异常,它会抛出该异常。因此,内部工作将自动设置内容长度。这也意味着,要将其设置为“0”,需要将实体设置为null。

        6
  •  0
  •   Alok    6 年前

    @约翰·里克斯的回答

        private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{
                @Override
                public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
                    request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present");
                }
            }
    HttpClient client = HttpClients.custom()
                    .addInterceptorFirst(new ContentLengthHeaderRemover())
                    .build();