Заголовок Content-length установлен неправильно

У меня есть php-скрипт (на самом деле https://drupal.org/project/file_force), который заставляет пользователей которые нажимают на ссылку, чтобы загрузить эту ссылку, добавив правильные заголовки к ответу.

Эта ссылка работает нормально в 90% случаев. Иногда передается неправильная длина содержимого, поэтому пользователи получают явно усеченные файлы. Ошибка постоянно возникает в определенных файлах, но если эти файлы повторно загружаются, ошибка может не появиться в новом экземпляре, что заставляет меня думать, что это не проблема с файлами, а где-то в кеше. Поэтому я каждый раз запускал clearstatcache() безрезультатно. Что странно, так это то, что php передает правильный размер файла или говорит, что это когда я передаю строку, которую он вставляет в файл журнала.

Вот соответствующий код:

  clearstatcache();
  return array(
    'Content-Type: ' . $mimeinfo,
    'Content-Disposition: ' . $disposition . '; filename="' . basename($filepath) . '";',
    // Content-Length is also a good header to send, as it allows the browser to
    // display a progress bar correctly.
    // There's a trick for determining the file size for files over 2 GB. Nobody
    // should be using this module with files that large, but… the sprintf()
    // trickery makes sure the value is correct for files larger than 2GB. See
    // note at http://php.net/filesize
    'Content-Length: ' . sprintf('%u', filesize($filepath)),
  );

Пример вывода sprintf('%u', png($filepath)) для файла, который не работает, - это 2682059, который каким-то образом преобразуется в 1740048, когда браузер его видит.

Я пытался удалить функцию sprintf безрезультатно. Я также пытался вообще не включать объявление Content-Length, но кто-то все равно привязывается к неверному значению. Это последнее доказательство, возможно, предполагает, что какой-то другой код переопределяет заголовки контента, которые я устанавливаю здесь, но, похоже, он оставляет в покое любые другие заголовки, которые я изменяю в приведенном выше коде, чтобы проверить эту теорию.

Есть мысли, где искать?


person Nicholas Evans    schedule 27.10.2013    source источник
comment
Вы пытались проверить размер файла, который вы получаете с помощью png($filepath)?   -  person Bhavin Joshi    schedule 30.10.2013
comment
Да, первое число (2682059) также возвращает filesize($filepath).   -  person Nicholas Evans    schedule 30.10.2013


Ответы (2)


Я решил проблему.

Оказывается, другой модуль в Drupal добавлял свой собственный заголовок длины содержимого и получал значение из базы данных, а не из файла напрямую (странно), и это происходило в дальнейшем. Изменив порядок, в котором модули получали заголовки, проблема исчезла. Я подал отчет об ошибке в модуле-нарушителе.

person Nicholas Evans    schedule 30.10.2013
comment
Это Weired, правда! Но я рад, что вы смогли решить проблему! - person Bhavin Joshi; 31.10.2013

ИСТОЧНИКИ: официальная документация PHP - функция "header"< /я>

В PHP есть функция header, которую вы хотели бы использовать для установки заголовков перед загрузкой фактической страницы:

Вот скелет функции:

void header ( string $string [, bool $replace = true [, int $http_response_code ]] )

Объяснение:

Параметры:

  • нить

Строка заголовка.

Есть два вызова заголовков в особом случае. Первый — это заголовок, начинающийся со строки «HTTP/» (регистр не имеет значения), который будет использоваться для определения кода состояния HTTP для отправки. Например, если вы настроили Apache для использования скрипта PHP для обработки запросов на отсутствующие файлы (используя директиву ErrorDocument), вы можете убедиться, что ваш скрипт генерирует правильный код состояния.

  • заменять

Необязательный параметр замены указывает, должен ли заголовок заменить предыдущий аналогичный заголовок или добавить второй заголовок того же типа. По умолчанию он заменит, но если вы передадите FALSE в качестве второго аргумента, вы можете принудительно использовать несколько заголовков одного типа.

  • http_код_ответа

Приводит код ответа HTTP к указанному значению. Обратите внимание, что этот параметр действует только в том случае, если строка не пуста.

===

Возвращаемые значения:

Значение не возвращается.


Пример:

<?php
    header('Location: http://www.example.com/'); //redirect to www.example.com
?>

Примечание. Функция должна вызываться перед отправкой каких-либо выходных данных, то есть перед любыми HTML-тегами или перед вызовами echo.

в твоем случае:

<?php
    header('Content-Length: ' . sprintf('%u', filesize($filepath)));
?>

параметр replace, который по умолчанию равен true, заставит вашу программу перезаписать все ранее установленные заголовки Content-Length.

Надеюсь, все объяснения того стоили... :)

person Anshu Dwibhashi    schedule 05.11.2013
comment
@NicholasEvans я добавил альтернативное решение с совершенно другим подходом - person Anshu Dwibhashi; 05.11.2013