我有一个问题,我的代码看起来很好我有一个状态200,正确的标题,但我创建的csv文件不会下载...
我没有错误,所以我不明白为什么......
如果你可以帮助我?
谢谢
这是我的代码:
namespace Rac\CaraBundle\Manager;
/* Imports */
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\StreamedResponse;
/* Local Imports */
use Rac\CaraBundle\Entity\Contact;
/**
* Class CSV Contact Importer
*
*/
class CSVContactImporterManager {
/**
* @var ObjectManager
*/
private $om;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var ValidatorInterface
*/
private $validator;
/**
* @var ContactManager
*/
private $contactManager;
/**
* @param EventDispatcherInterface $eventDispatcher
* @param ObjectManager $om
* @param Contact $contactManager
*
*/
public function __construct(
EventDispatcherInterface $eventDispatcher, ObjectManager $om, ValidatorInterface $validator, ContactManager $contactManager
) {
$this->eventDispatcher = $eventDispatcher;
$this->om = $om;
$this->validator = $validator;
$this->contactManager = $contactManager;
}
public function getExportToCSVResponse() {
// get the service container to pass to the closure
$contactList = $this->contactManager->findAll();
$response = new StreamedResponse();
$response->setCallback(
function () use ($contactList) {
//Import all contacts
$handle = fopen('php://output', 'r+');
// Add a row with the names of the columns for the CSV file
fputcsv($handle, array('Nom', 'Prénom', 'Société', 'Position', 'Email', 'Adresse', 'Téléphone', 'Téléphone mobile'), "\t");
$header = array();
//print_r($contactList);
foreach ($contactList as $row) {
fputcsv($handle, array(
$row->getFirstName(),
$row->getLastName(),
$row->getCompany(),
$row->getPosition(),
$row->getEmail(),
$row->getAddress(),
$row->getPhone(),
$row->getMobile(),
), "\t");
}
fclose($handle);
}
);
$response->headers->set('Content-Type', 'application/force-download');
$response->headers->set('Content-Disposition', 'attachment; filename="export.csv"');
return $response;
}
我的控制员:
use Rac\CaraBundle\Entity\Contact;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use UCS\Bundle\RichUIBundle\Controller\BaseController;
use UCS\Bundle\RichUIBundle\Serializer\AbstractListSerializer;
/**
* Contact BackOffice Environment Controller.
*
*
*
* @Route("/contact_environment")
*/
class ContactEnvironmentController extends BaseController{
/* My code here..*/
/**
* @Route("/export", name="contact_environment_export",options={"expose"=true})
* @Method("GET")
*
* @return type
*/
public function exort(){
$manager = $this->get("cara.csv_contact_importer_manager");
return $manager->getExportToCSVResponse();
}
}
我的标题:
Cache-Control:no-cache, private
Connection:close
Content-Disposition:attachment; filename="export.csv"
Content-Type:application/force-download
答案 0 :(得分:2)
以下是作者要求的基于响应的解决方案。在此设计中,csv服务仅返回csv文本。响应在控制器中生成。
csv生成器:
class ScheduleGameUtilDumpCSV
{
public function getFileExtension() { return 'csv'; }
public function getContentType() { return 'text/csv'; }
public function dump($games)
{
$fp = fopen('php://temp','r+');
// Header
$row = array(
"Game","Date","DOW","Time","Venue","Field",
"Group","HT Slot","AT Slot",
"Home Team Name",'Away Team Name',
);
fputcsv($fp,$row);
// Games is passed in
foreach($games as $game)
{
// Date/Time
$dt = $game->getDtBeg();
$dow = $dt->format('D');
$date = $dt->format('m/d/Y');
$time = $dt->format('g:i A');
// Build up row
$row = array();
$row[] = $game->getNum();
$row[] = $date;
$row[] = $dow;
$row[] = $time;
$row[] = $game->getVenueName();
$row[] = $game->getFieldName();
$row[] = $game->getGroupKey();
$row[] = $game->getHomeTeam()->getGroupSlot();
$row[] = $game->getAwayTeam()->getGroupSlot();
$row[] = $game->getHomeTeam()->getName();
$row[] = $game->getAwayTeam()->getName();
fputcsv($fp,$row);
}
// Return the content
rewind($fp);
$csv = stream_get_contents($fp);
fclose($fp);
return $csv;
}
控制器:
public function renderResponse(Request $request)
{
// Model is passed via request
$model = $request->attributes->get('model');
$games = $model->loadGames();
// The csv service
$dumper = $this->get('csv_dumper_service');
// Response with content
$response = new Response($dumper->dump($games);
// file prefix was injected
$outFileName = $this->prefix . date('Ymd-Hi') . '.' . $dumper->getFileExtension();
$response->headers->set('Content-Type', $dumper->getContentType());
$response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"',$outFileName));
return $response;
}
答案 1 :(得分:1)
这是一个流媒体Symfony响应,工作正常。该类创建了一个要下载的文件,其中包含导出的数据。
class ExportManagerService {
protected $filename;
protected $repdata;
public function publishToCSVReportData(){
$repdata = $this->repdata;
// array check
if (is_array($repdata)){
$response = new StreamedResponse();
$response->setCallback(
function () use ($repdata) {
$handle = fopen('php://output', 'r+');
foreach ($repdata as $row) {
$values = $row['values'];
$position = $row['position'];
$fileData = $this->structureDataInFile($values, $position);
fputcsv($handle, $fileData);
}
fclose($handle);
}
);
} else{
throw new Exception('The report data to be exported should be an array!');
}
$compstring = substr($this->filename,-4);
if($compstring === '.csv'){
// csv file type check
$response->headers->set('Content-Type', 'application/force-download');
$response->headers->set('Content-Disposition', 'attachment; filename='.$this->filename);
} else { throw new Exception('Incorrect file name!');}
return $response;
}
public function structureDataInFile(array $values, $position){
switch ($position){
case 'TopMain':
for ($i = 0; $i < 4; $i++){
array_unshift($values, ' ');
}
return $values;
break;
case 'Top':
$space = array(' ', ' ', ' ');
array_splice($values,1,0,$space);
return $values;
break;
case 'TopFirst':
for ($i = 0; $i < 1; $i++){
array_unshift($values, ' ');
}
$space = array(' ', ' ');
array_splice($values,2,0,$space);
return $values;
break;
case 'TopSecond':
for ($i = 0; $i < 2; $i++){
array_unshift($values, ' ');
}
$space = array(' ');
array_splice($values,3,0,$space);
return $values;
break;
case 'TopThird':
for ($i = 0; $i < 3; $i++){
array_unshift($values, ' ');
}
return $values;
break;
default:
return $values;
}
}
/*
* @var array
*/
public function setRepdata($repdata){
$this->repdata = $repdata;
}
/*
* @var string
*/
public function setFilename($filename){
$this->filename = $filename;
}
}
答案 2 :(得分:1)
这是一种更短的方式:)
/**
* Class CsvResponse
*/
class CsvResponse extends StreamedResponse
{
/**
* CsvResponse constructor.
*
* @param array $rows
* @param string $fileName
*/
public function __construct(array $rows, $fileName)
{
parent::__construct(
function () use ($rows) {
$this->convertArrayToCsv($rows);
},
self::HTTP_OK,
[
'Content-Disposition' => sprintf('attachment; filename="%s"', $fileName),
'Content-Type' => 'text/csv',
]
);
}
/**
* @param array $rows
*
*/
private function convertArrayToCsv(array $rows)
{
$tempFile = fopen('php://output', 'r+b');
foreach ($rows as $row) {
fputcsv($tempFile, $row);
}
fclose($tempFile);
}
}
答案 3 :(得分:1)
这是我使用过不止一次的简单实现,实际上按照要求使用了 StreamRepsonse
。
这是一个新的响应类,它扩展了 StreamResponse
并具有类似的签名。还接受 $separator
和 $enclosure
参数,例如需要使用分号 (;
) 而不是逗号等。
如果需要创建更大的文件,它会在 php://temp
中创建 CSV 以尝试节省内存,并使用 stream_get_contents
一次检索一点。
class StreamedCsvResponse extends StreamedResponse
{
private string $filename;
public function __construct(
private array $data,
?string $filename = null,
private string $separator = ',',
private string $enclosure = '"',
$status = 200,
$headers = []
) {
if (null === $filename) {
$filename = uniqid() . '.csv';
}
if (!str_ends_with($filename, '.csv')) {
$filename .= '.csv';
}
$this->filename = $filename;
parent::__construct([$this, 'stream'], $status, $headers);
$this->setHeaders();
}
private function setHeaders(): void
{
$this->headers->set(
'Content-disposition',
HeaderUtils::makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $this->filename)
);
if (!$this->headers->has('Content-Type')) {
$this->headers->set('Content-Type', 'text/csv; charset=UTF-8');
}
if (!$this->headers->has('Content-Encoding')) {
$this->headers->set('Content-Encoding', 'UTF-8');
}
}
public function stream(): void
{
$handle = fopen('php://temp', 'r+b');
$this->encode($this->data, $handle);
if (!is_resource($handle)) {
return;
}
rewind($handle);
while ($t = stream_get_contents($handle, 1024)) {
echo $t;
}
fclose($handle);
}
private function encode(array $data, $handle): void
{
if (!is_resource($handle)) {
return;
}
foreach ($data as $row) {
fputcsv($handle, $row, $this->separator, $this->enclosure);
}
}
}