【发布时间】:2019-01-03 15:08:37
【问题描述】:
在 CakePHP 3.5.13 中,我有一个控制器动作如下:
class ReportController extends AppController
{
public function download($id, $format)
{
}
}
我想要做的是将报告 ID 和格式(例如 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 中按字面意思输出:
我猜这个问题是由于响应实际上是 HTML 而不是 CSV,但我不确定。
我的问题是,是否可以以这种方式使用 .ctp 文件并以指定格式将它们作为下载输出到浏览器?
我知道路由和 URL 扩展还可以做其他事情,但这个问题与这些无关。我也不想使用插件/扩展。我想知道是否可以使用$this->render() 并让Cake 渲染一个模板,该模板以请求的格式发送到浏览器以供下载?
【问题讨论】:
-
我同意下面的观点,github.com/FriendsOfCake/cakephp-csvview 应该在这里使用,这样更干净。