CakePHP 3 выходной .ctp шаблон в виде файла CSV - PullRequest
0 голосов
/ 03 января 2019

В CakePHP 3.5.13 у меня есть действие Controller следующим образом:

class ReportController extends AppController
{
    public function download($id, $format)
    {

    }
}

Что я хочу сделать, это передать параметры для идентификатора и формата отчета (например, XLSX, CSV) в downloadфункция, например, /report/download/123/csv будет получать данные для отчета 123 и выводить их как CSV.

У меня есть все данные, необходимые для моего отчета в массиве, $data.Я хочу создать отдельные шаблоны (файлы .ctp) для форматирования моих данных в каждом из желаемых форматов, а затем с помощью функции download() отправить их в браузер для загрузки.

Поэтому я адаптировал свою функцию какследует:

public function download($id, $format)
{
    $data = // ... Model data in array format

    $filename = '123'; // filename for the download

    switch ($format):
        case 'csv':
            header('Content-type: text/csv');
            header('Content-Disposition: attachment; filename="'.$filename.'.csv"');

            $this->viewBuilder()->setLayout('ajax');
            $this->set('data', $data);
            $this->render('download_csv');
        break;
    endswitch;
}

Это правильно отображает шаблон, который у меня есть от Template/Report/download_csv.ctp.Он также правильно отображается в макете ajax ($this->viewBuilder()->setLayout('ajax'); означает, что он использует Template/Layout/ajax.ctp и, следовательно, не содержит HTML-код «оболочки»).

При посещении /report/download/123/csv браузер отправляет файл с именем 123.csv с данными, которые я запросил.Однако тип ответа - text/html, а не text/csv, как указано в действии моего контроллера.

Это приводит к искажению содержимого файла - он обрабатывает его как HTML вместо CSV.Например, если в моем шаблоне download_csv.ctp есть следующее:

"Field 1", "123\n456",
"Field 2", "789"

Он выводится буквально, как показано здесь в Excel:

enter image description here

Я предполагаю, что эта проблема связана с тем фактом, что Ответ на самом деле является HTML, а не CSV, но я не уверен.

У меня вопрос, возможно ли использовать файлы .ctp втаким образом и вывести их в виде загрузок в браузер в указанном формате?

Я знаю, что есть другие вещи, которые можно сделать с помощью маршрутизации и расширений URL, но этот вопрос не касается этих вопросов.Я также не хочу использовать плагины / расширения.Я хочу знать, возможно ли использовать $this->render() и сделать ли Cake шаблон для отправки в браузер для загрузки в запрошенном формате?

1 Ответ

0 голосов
/ 03 января 2019

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

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

При этом контроллеры не должны выводить данные, включая заголовки! Вывод данных в контроллер может привести к всевозможным проблемам: от данных, не распознаваемых в тестовой среде, до невозможности отправки заголовков и даже к обрезанию данных. Вместо этого используйте подходящие методы объекта ответа, чтобы подготовить соответствующий ответ для загрузки, в вашем случае вы ищете withType() и withDownload(), например:

case 'csv':
    $this->response = $this->response->withType('csv');
    $this->response = $this->response->withDownload($filename. '.csv');

    $this->viewBuilder()->setLayout('ajax');
    $this->set('data', $data);
    $this->render('download_csv');
break;

Это добавит правильные заголовки Content-Type и Content-Disposition.

Смотри также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...