0

大きなファイルのRestTemplateに関する質問がありました。最大のコンテンツ長がありますか、明示的に設定されていても自動的に変更されますか?Spring RestTemplate大きなファイルContentLength Autoが変更されました

HTTP PUTコマンドでCDN(Akamai)に送信したいファイルが5GBあります。私は(Javaヒープスペースエラーを避けるために)以下のように設定しましたが、コマンドが実行されるとContent-Lengthが変更されることに気付きました。

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

し、ファイルを送信するためにコール:

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を報告し、リクエストがその長さに達したときに接続が殺されます。

Javaがエラーを報告:

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

編集:私はそうのようなContent-Lengthをハードコーディング

いくつかのより多くの観測、:headerValues.put( "のContent-Length"、「3764589480 "); 実際にContent-Lengthフィールドは送信されず、代わりにTransfer-Encoding:chunkedヘッダーが送信されます。

だから私はより多くのテストを実行し、これは何が起こるかです:

ハードコードコンテンツの長さ:チャールズ

"1064589480" の結果:コンテンツ長を送信:1064589480

"2064589480":コンテンツを送信-length:2064589480

"3064589480" は:コンテンツ長を削除し、転送エンコーディングを追加します: "3764589480"

チャンク:

"4294967295"

チャンク:コンテンツ長を削除し、転送エンコードが追加のContent-Lengthを送信します::

"4294967296"

チャンク:コンテンツ長を削除し、転送エンコードが追加し、 "0"、即時クラッシュし、

「4764589480」書かれてあまりにも多くのバイト:コンテンツ長を送信:「469622184」

「5764589480」:コンテンツ長を送信:私の知る限り推測できるよう「1469622184」

、一定で番号、RestTemplateはContent-Lenから転送符号化へのgth。 4294967295を通過すると、Content-Lengthを再び0に戻し始めます。 これは、4294967295より高い値を決して指定しないことです。そのしきい値を超えている場合は、単に4294967295に設定し、RestTemplateはそれを転送エンコーディング:とにかくチャンク。 オーバーフロー/精度ポイントの問題がありますか?

答えて

0

AFAIK、4294967295バイトは、[Content Length]フィールドに入力できる最大数です。この量を超えていても、RestTemplateは自動的にContent-LengthからTransfer-Encoding:chunkedに切り替えるので、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); 
関連する問題