Как вернуть строку клиенту после установки заголовка

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

//code snippet: $filename = basename($datei); $size = filesize($datei); $this->response->setHeader('Content-Type', "application/force-download", TRUE); $this->response->setHeader('Content-Disposition', 'attachment; filename='.$filename , TRUE); $this->response->setHeader('Content-Length', $size, TRUE); return "TEST"; //<--code will never go this far, it is ignored 

Загрузка работает. Но я никогда не получаю что-то возвращенное как ответ, но заголовок. Как я могу вернуть что-то, например строку, после начала загрузки?

Кажется, невозможно вернуть что-то клиенту после установки заголовка.


ЗАДНИЙ ПЛАН

В основном моя цель состояла в том, чтобы показать и скрыть значок spinner, например, показать значок spinner внутри кнопки загрузки, пока файл все еще загружается, и скрыть его снова после завершения загрузки. Поэтому, чтобы узнать, закончилась ли загрузка, я подумал, что могу просто вернуть что-то с сервера клиенту, чтобы клиент знал об этом, например, «загрузка прошла успешно».

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

Вы не можете . Не тратьте свое время на поиски взлома, а скорее создайте страницу для загрузки.

Когда вы сообщаете браузеру (используя заголовки), что вы собираетесь предоставить файл для загрузки, как здесь

 $this->response->setHeader('Content-Type', "application/force-download", TRUE); 

Затем все довольно недавние браузеры последуют за этим советом и загружают файл, после чего им все равно, если PHP сумеет что-то повторить в конце или нет, им это не нужно.

Ваш PHP-код не игнорируется , он отлично обрабатывается. PHP не мешает вам иметь какой-либо код после предоставления некоторых заголовков для браузера. Просто, как только вы сказали клиенту, что вы собираетесь вернуть файл для загрузки, он не беспокоит, какой другой текст вы хотите вывести. На самом деле это будет считаться частью файла загрузки. Вы не видите его в своем файле, потому что его return которое не полезно в этом контенте, попробуйте echo .

Когда вы предоставляете заголовок Content Type, вам следует отправить контент именно этого типа, если вы хотите, чтобы браузер успешно понял ответ вашего сервера.

Посмотрите на все основные сайты загрузки, почти у всех из них есть их настройки загрузки, поэтому, когда вы нажимаете ссылку для загрузки, вы перенаправляетесь на другую страницу, в которой говорится: «Ваша загрузка начнется в ближайшее время …», и между тем они инициируют другой запрос к их загружайте страницу, которая делает именно это; предоставляет файл для загрузки.

Таким образом, в одном запросе вы не можете смешивать их вместе с любым количеством совместимых браузеров.

Чтобы закончить текущий скрипт, вы можете использовать return , однако, когда он используется в скрипте верхнего уровня (как у вас есть), он завершит выполнение, но не вернет какое-либо возвращаемое значение или не выведет что-либо как часть ответа HTTP . Вам нужно exit для этого (но см. Позже).

return может возвращать значение только вызывающим скриптам:

  • при использовании в include / require, это закончится тем, что включает / требует и передает значение обратно в вызывающий скрипт
  • при использовании в функции он прекратит эту функцию и передаст значение обратно в вызывающий скрипт

Чтобы закончить текущий скрипт и вывести значение как часть ответа HTTP, вы можете использовать exit ( http://php.net/manual/en/function.exit.php ) или die (то же, что и exit). Но exit может изменить свое поведение при передаче параметра:

  • если строка будет отправлена ​​как часть ответа HTTP
  • если это целое число, он будет использовать это как код выхода (для использования в командной строке).

Чтобы вывести что-либо, чтобы получить «возвращенный» как часть ответа HTTP, используйте echo . ( http://php.net/manual/en/function.echo.php ). Это выведет все, что может быть преобразовано в строку (т. Е. Для вывода целого числа или строки) и не будет изменять поведение, если целое число или строка будут выполнены.


Таким образом, самый безопасный вариант:

  • всегда используйте echo чтобы отправить что-то обратно как часть ответа HTTP
  • всегда использовать exit для завершения исполнения;
  • использовать возврат внутри функций или файлов, которые, как вы знаете, будут «включены» (и, необязательно, передать возвращаемое значение)

В идеале (чтобы избежать потенциальной неоднозначности кода) для ответа HTTP, не добавляйте возвращаемые значения для выхода, если вы не программируете интерфейс командной строки. т.е. для HTTP, используйте

 // Outputs something and exists echo 'TEST'; exit; 

или

 // Outputs something and exists echo 1; exit; 

Если вы выводите файл (а не переменную, readfile() в памяти), посмотрите readfile() ( http://php.net/manual/en/function.readfile.php ), который выведет поток файлов в HTTP ответ. (Последовал exit; )

 // Outputs a file to HTTP response readfile('/path/To/My/File/MyFile.txt'); exit; 

* Бонусная нота: exit , echo и return не являются функциями, как таковыми, а являются языковыми конструкциями. Возвращаемые значения для exit и return не должны указываться в скобках. Он будет работать, но руководство по PHP рекомендует против него. echo может использовать параметры, и действительно, вы должны, если вы передаете более одного значения для вывода.

Неправильно:

  • Выход ( 'Test');
  • вернуться ( 'TEST');

Верный:

  • exit 'TEST';
  • return 'TEST';
  • echo 'TEST';
  • echo ('TEST', 'MORE'),

Ну, я использую среду MVC, и в моем контроллере у меня есть метод, который делает это, и нет необходимости повторно загружать родительскую страницу с начала загрузки:

 // Define headers header("Cache-Control: public"); header("Content-Description: File Transfer"); header("Content-Disposition: attachment; filename=$file_name"); header("Content-Type: application/zip"); header("Content-Transfer-Encoding: binary"); // Read the file readfile($filePath); exit;