@memba

PHP cURL отправка файла PUT запросом в OpenStack не работает под Linux ОС

Добрый день!

У меня возникла некоторая проблема с оправкой файлов в хранилище под управлением OpenStack, хотя оно тут не причем.

Суть: Мы конектимся к хранилищу и оправляем файл заданный строкой.
Кусок кода:

$string = 'file_string'; // это тестовая строка из которой будет создан файл

$file_res = fopen('php://temp', 'w+b');
fwrite($file_res, $string);
fseek($file_res, 0);

$file_size = mb_strlen($string); // получаем размер файла
$file_md5 = md5($string); // это будет E-tag
$file_type = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $string); // пытаемся определить тип файла по строке

if($file_type === false) return false;

$headers = array();
$headers[] = 'X-Auth-Token: '.$auth_key; // ключ авторизации
$headers[] = 'ETag: '.$file_md5;
$headers[] = 'Content-Length: '.$file_size;
$headers[] = 'Content-Type: '.$file_type;

$ch = curl_init($url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_NOBODY, true);	
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_USERAGENT, "MyAgent");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, $file_res);
curl_setopt($ch, CURLOPT_INFILESIZE, $file_size);

$content = curl_exec($ch);

$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

curl_close($ch);
fclose($file_res);


И так. Под Windows все отлично работает и файл создается в хранилище, но под Linux я получаю ошибку 400 Bad Request. Причем проверил я это на 5 разных хостинг площадках. Любая версия cURL под Linux получает 400 Bad Request.

Посмотрев, что за заголовки отправляются под Windows и под Linux я выяснил что:

1. Под Windows все правильно
2. Под Linux идет заголовок Content-Length 2 раза!

Если я не хочу что бы заголовок Content-Length шел 2 раза, я могу убрать из массива $headers добавление заголовка, но тогда это не будет работать на Winows версией.

Я могу отключить CURLOPT_INFILESIZE, на Windows не работает вообще, на Linux + ко всему добавляется Transfer-Encoding: chunked и заголовок Content-Length уже не учитывается - файл отправляется.

Вообщем что бы всё работало там и там в данный момент я не оправляю Content-Length и убрал CURLOPT_INFILESIZE, добавив Transfer-Encoding: chunked.

Вопрос: Что это за дела такие?
  • Вопрос задан
  • 3573 просмотра
Пригласить эксперта
Ответы на вопрос 1
alekciy
@alekciy
Вёбных дел мастер
Если я не хочу что бы заголовок Content-Length шел 2 раза, я могу убрать из массива $headers добавление заголовка, но тогда это не будет работать на Winows версией.

А почему бы не отслеживать платформу и добавлять или нет указанный заголовок?
if (PHP_OS != 'Linux) {
    $headers[] = 'Content-Length: '.$file_size;
}


Имхо, на linux как раз поведение правильное ибо файл известен и библиотека сама может провести расчеты связанные с заголовками и размерами.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы