0

대용량 파일로 RestTemplate에 대한 질문이 있습니다. 최대 콘텐츠 길이가 있습니까? 명시 적으로 설정되었지만 자동으로 변경됩니까?봄 RestTemplate 대형 파일 ContentLength 자동 변경

HTTP PUT 명령을 통해 내 CDN (Akamai)으로 보내려는 파일이 5GB입니다. 나는 아래처럼 (자바 힙 공간 오류를 피하기 위해) 그것을 설정했다. 그러나 나는 명령이 실행될 때 Content-Length가 변경된다는 것을 알아 차렸다.

Resource resource = new FileSystemResource(localFile); 

    HttpHeaders headers = new HttpHeaders(); 
    Map<String, String> headerValues = new HashMap<String, String>(); 
    headerValues.put("X-Akamai...", value); //There are more headers, but you can assume this is correctly done as I've been able to transmit smaller files 
    headerValues.put("Host", host); 
    headers.setAll(headerValues); 
    headers.setContentType(MediaType.MULTIPART_FORM_DATA); 


    //I've tried using this and not using this but the result is 
    //the same, the request sent changes the value to 1469622184 
    headers.setContentLength(resource.contentLength()); 


    System.out.println(headers.getContentLength()); //Result is: 5764589480 
    HttpEntity<Resource> uploadRequest = new HttpEntity<Resource>(resource, headers); 
    response = restTemplateUpload.exchange(hostPath, HttpMethod.PUT, uploadRequest, String.class); 

찰스 프록시 콘텐츠 길이 1469622184를보고하고 요청이 그 길이에 도달하면 연결이 살해됩니다 :

@Autowired 
    @Qualifier("restTemplateUpload") 
    public void setRestTemplateUpload(RestTemplate restTemplateUpload) 
    { 
     this.restTemplateUpload = restTemplateUpload; 
     SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); 
     requestFactory.setBufferRequestBody(false); 
     restTemplateUpload.setRequestFactory(requestFactory); 
    } 

그리고 호출은 파일을 보낼 수 있습니다. 3,764,589,480 ", headerValues.put ("콘텐츠 길이 "

org.springframework.web.client.ResourceAccessException: I/O error on PUT request for "http://hidden.com/path/largefile.txt": too many bytes written;"

편집 :

좀 더 관찰, 내가 지금 같은 콘텐츠 길이를 하드 때

자바는 오류를보고 "); Content-Length 필드가 실제로 전송되지 않고 대신 Transfer-Encoding : chunked가 전송됩니다.

그래서 나는 더 많은 테스트를 실행하고이 일어나는 것이다 :

금지 된 내용 길이 : 찰스

"1064589480"으로 검색 결과 : 1064589480

"2064589480": 콘텐츠 길이를 보냅니다 컨텐츠 전송 - 길이 : 2,064,589,480

"3064589480는"콘텐츠 길이를 제거, 전송 인코딩을 추가합니다 :

"3764589480"

청크 :

"4294967295"

청크 : 콘텐츠 길이를 제거, 전송 인코딩이 추가 콘텐츠 길이를 보냅니다 :

"4294967296"

청크 : 콘텐츠 길이를 제거, 전송 인코딩이 추가 "0", 즉시 충돌을, 콘텐츠 길이가 보냅니다 : "469622184"

"5764589480"콘텐츠 길이가 전송 : 너무 많은 바이트

"4764589480"

작성 "1469622184"

지금까지 내가 어떤에서 추론 할 수있는 번호, RestTemplate은 Content-Len에서 gth를 Transfer-Encoding으로 변환합니다. 일단 4294967295를 통과하면 Content-Length를 다시 0으로 다시 전달하기 시작합니다. 내 최선의 해결 방법은 4294967295보다 높은 값을 지정하지 않는 것입니다. 임계 값을 초과하면 4294967295로 설정하면 RestTemplate에서 다음과 같이 변경됩니다 전송 - 인코딩 : 아무렇게나. 오버 플로우/정밀도 문제가 있습니까?

답변

0

AFAIK, 4294967295 바이트는 Content Length 필드에 넣을 수있는 최대 숫자입니다. 이 양이 넘더라도 RestTemplate이 자동으로 Content-Length 사용에서 Transfer-Encoding 사용으로 전환되므로 4294967295로 설정하는 것이 좋습니다. 청크로 묶여 어떤 크기로든 상관 없습니다.

public static final String MAX_TRANSFER_SIZE = "4294967295"; 

... 

HttpHeaders headers = new HttpHeaders(); 
Map<String, String> headerValues = new HashMap<String, String>(); 
if (resource.contentLength() > Long.parseLong(MAX_TRANSFER_SIZE)) 
{ 
     // This is as high as the content length can go. At this size, 
     // RestTemplate automatically converts from using Content-Length to 
     // using Transfer-Encoding:chunked. 
     headerValues.put("Content-Length", MAX_TRANSFER_SIZE); 
} 
headers.setAll(headerValues);