0

У вас есть вопрос по RestTemplate с большими файлами. Существует ли максимальная длина контента и/или автоматически изменяется, несмотря на то, что он явно установлен?Spring RestTemplate Большие файлы ContentLength Auto Changed

У меня есть файл размером 5 ГБ, который я хочу отправить на мой CDN (Akamai) с помощью команды HTTP PUT. Я установил его, как показано ниже (чтобы избежать ошибок кучи 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); 

Charles Proxy сообщает Content-Length 1469622184 и соединение получает убиты, когда запрос достигает этой длины.

Java сообщает об ошибке:

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

EDIT:

еще несколько наблюдений, когда я жёстко Content-Length так: headerValues.put ("Content-Length", «3764589480 «); Поле Content-Length фактически не отправляется, и вместо этого отправляется сообщение Transfer-Encoding: chunked.

Так что я провел несколько тестов, и это то, что происходит:

Запрограммированные Содержание Длина: Результат в Charles

"1064589480": Посылает Content-Length: 1064589480

"2064589480": Посылает Содержание -Длина: 2064589480

"3064589480": Удаляет Content-Length, добавляет Transfer-Encoding: фрагментированное

"3764589480": Удаляет Content-Length, добавляет Transfer-Encoding: фрагментированное

"4294967295": Удаляет Content-Length, добавляет Transfer-Encoding: фрагментированное

"4294967296": Посылает Content-Length: "0", Immediate Краш, слишком много байт написано

"4764589480": Посылает Content-Length: "469622184"

"5764589480": Посылает Content-Length: "1469622184"

насколько я могу вывести, на определенный number, RestTemplate переключится с Content-Len gth к Transfer-Encoding. Как только он пройдет 4294967295, он снова начнет передавать Content-Length до 0. Мое лучшее разрешение для этого - никогда не указывать значение выше 4294967295. Если оно выше этого порога, просто установите его на 4294967295, а RestTemplate изменит его на Кодирование передачи: все равно. Есть ли какие-то проблемы с переполнением/точностью?

ответ

0

AFAIK, 4294967295 bytes - максимальное число, которое вы можете поместить в поле Content Length. Даже если это превысит эту сумму, я бы рекомендовал установить ее на 4294967295, поскольку RestTemplate автоматически переключится с использования Content-Length на использование Transfer-Encoding: chunked, поэтому не имеет значения, какой размер вы поставили в любом случае.

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); 
Смежные вопросы