我正在使用Symfony 2创建一个“下载”控制器,它的唯一目的是发送标题,以便我可以强制下载.csv文件,但它无法正常工作。
$response = new Response();
$response->headers->set('Content-Type', "text/csv");
$response->headers->set('Content-Disposition', 'attachment; filename="'.$fileName.'"');
$response->headers->set('Pragma', "no-cache");
$response->headers->set('Expires', "0");
$response->headers->set('Content-Transfer-Encoding', "binary");
$response->headers->set('Content-Length', filesize($fileName));
$response->prepare();
$response->sendHeaders();
$response->setContent(readfile($fileName));
$response->sendContent();
$fileName
是一个"info.csv"
字符串。这是我在我的控制器内的行为,没有退货声明。当我尝试返回Response
对象时,文件的内容显示在浏览器中,而不是我想要的结果。
我发现的问题是,在某些页面中,我确实得到了info.csv file
,但在其他一些页面中,我得到的是一条消息:
No webpage was found for the web address: http://mywebpage.com/download
Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.
我完全确定该文件存在,所以必定还有其他问题。此外,routing.yml工作正常,因为我从其他页面获取文件也链接到该路径。 Apache错误日志没有显示任何相关内容。
有没有人强行在Symfony 2上下载.csv文件?如果是这样,我做错了什么?
答案 0 :(得分:35)
这是一个在生产中运作良好的最小例子:
class MyController
public function myAction()
$response = $this->render('ZaysoAreaBundle:Admin:Team/list.csv.php',$tplData);
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="teams.csv"');
return $response;
如果您愿意,可以使用新响应和response-> setContent替换渲染调用。
你对控制器内部没有返回语句的评论令人费解。控制器返回响应。让框架负责将内容发送到浏览器。
答案 1 :(得分:7)
我意识到这篇文章有点陈旧,奇怪的是,除了这篇文章在stackoverflow之外,几乎没有关于如何在symfony 2中进行CSV导出的好资源。
无论如何,我将上面的例子用于客户竞赛网站并且效果很好。但是今天我收到了一封电子邮件,经过我自己的测试后,代码已经坏了 - 我能够通过少量结果获得下载工作,但是数据库现在可以导出超过31,000行,它只是显示文本或者铬,基本上什么也没做。
对于任何有大数据导出问题的人来说,这就是我为了上班而做的事情,基本上做了Cerad建议的替代方式:
$filename = "export_".date("Y_m_d_His").".csv";
$response = $this->render('AppDefaultBundle:Default:csvfile.html.twig', array('data' => $data));
$response->setStatusCode(200);
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Description', 'Submissions Export');
$response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
$response->headers->set('Content-Transfer-Encoding', 'binary');
$response->headers->set('Pragma', 'no-cache');
$response->headers->set('Expires', '0');
$response->prepare();
$response->sendHeaders();
$response->sendContent();
编辑:经过更多测试并提高允许的最大秒数后,我意识到之前的代码是在顶部打印出标题,所以我已经更新了代码。
答案 2 :(得分:6)
这对我有用,可以导出CSV和JSON。
Twig文件命名为:export.csv.twig,export.json.twig
控制器:
class PrototypeController extends Controller {
public function exportAction(Request $request) {
$data = array("data" => "test");
$format = $request->getRequestFormat();
if ($format == "csv") {
$response = $this->render('PrototypeBundle:Prototype:export.' . $format . '.twig', array('data' => $data));
$filename = "export_".date("Y_m_d_His").".csv";
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
return $response;
} else if ($format == "json") {
return new Response(json_encode($data));
}
}
}
路由:
prototype_export:
pattern: /export/{_format}
defaults: { _controller: PrototypeBundle:Prototype:export, _format: json }
requirements:
_format: csv|json
The Twigs:
export.csv.twig(在这里做你的逗号分隔,这只是一个测试)
{% for row in data %}
{{ row }}
{% endfor %}
export.json.twig(数据发送json_encoded,此文件为空)
希望这有帮助!
答案 3 :(得分:0)
这就是我设法让Silex返回CSV的方法:
// $headers in an array of strings
// $results are the records returned by a PDO query
$stream = function() use ($headers, $results) {
$output = fopen('php://output', 'w');
fputcsv($output, $headers);
foreach ($results as $rec)
{
fputcsv($output, $rec);
}
fclose($output);
};
return $app->stream($stream, 200, array(
'Content-Type' => 'text/csv',
'Content-Description' => 'File Transfer',
'Content-Disposition' => 'attachment; filename="test.csv"',
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
));
您可能还需要使用Javascript做一些Jiggery Pokery(我正在通过AJAX下载),但这post是使它工作所需的全部。
答案 4 :(得分:0)
您可以在每种情况下使用的简单功能,可导出csv以供下载...
public function getResponse(array $data, $filename, $headers = array())
{
if(substr(strtolower($filename), -4) == '.csv') {
$filename = substr($filename, 0, -4);
}
$tmpFile = $this
->_getContainer()
->get('kernel')
->getRootDir()
. '/../var/tmp_'.substr(md5(time()),0,5);
if(file_exists($tmpFile)) unlink($tmpFile);
$handle = fopen($tmpFile, 'w');
foreach ($data as $i => $row) {
$row = (array) $row;
if($i == 0) fputcsv($handle, array_keys($row));
fputcsv($handle, $row);
}
fclose($handle);
$Response = new Response(file_get_contents($tmpFile));
unlink($tmpFile);
$filename = preg_replace('[^a-z0-9A-Z_]', '', $filename);
$headers = array_merge([
'Expires' => 'Tue, 01 Jul 1970 06:00:00 GMT',
'Cache-Control' => 'max-age=0, no-cache, must-revalidate, proxy-revalidate',
'Content-Disposition' => 'attachment; filename='.$filename.'.csv',
'Content-Type' => 'text/csv',
'Content-Transfer-Encoding' => 'binary',
], $headers);
foreach ($headers as $key => $val) {
$Response->headers->set($key, $val);
}
return $Response;
}
答案 5 :(得分:-1)
如何使用Sonata的导出器:
use Exporter\Writer\CsvWriter;
/**
* @param array $orders
*/
public function exportToCsv($orders)
{
$rootdir = $this->get('kernel')->getRootDir();
$filename = $rootdir . '/data/orders.csv';
unlink($filename);
$csvExport = new CsvWriter($filename);
$csvExport->open();
foreach ($orders as $order)
{
$csvExport->write($order);
}
$csvExport->close();
return;
}
如果文件已经存在,它会崩溃,因此unlink-command。