php symfony中setContent()后的ZipArchive已损坏



在symfony中发送包含任何类型文件的zip存档时,我有一个非常奇怪的行为。问题是,我从浏览器下载的zip文件在文件的开头包含了一个额外的"位"。

下面是我的代码:

$tmpFileName = tempnam("/tmp", "xb_");
$zip = new ZipArchive();
$zip->open($tmpFileName, ZipArchive::CREATE);
$zip->addFile('[directory_inside_webspace]/test.pdf', 'myTest.pdf');
$zip->close();
$this->getResponse()->clearHttpHeaders();
$this->getResponse()->setContent(file_get_contents($tmpFileName));
$this->getResponse()->setHttpHeader('Content-Type', 'application/zip');
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename=archive.zip');
return sfView::NONE;

奇怪的是。/tmp下的临时zip文件就可以了。我可以毫无问题地提取它。但是浏览器发给我的文件是坏的。当我在十六进制编辑器中打开它们时,前几个字节看起来像:

working file:      50 4B 03 04 14 00 00 
corrupt file:   0A 50 4B 03 04 14 00 00

当我从损坏的文件中删除额外的'0A'时,我可以毫无问题地打开它。它现在与在/tmp中创建的tmp文件完全相同。

以前有人有过这样的行为吗??我在这个问题上卡住了4天多了,我找不到错误。我在另一个symfony模块中使用完全相同的代码,它在那里工作。有什么想法吗?

——更新

问题与zipArchive或setContent无关。我在函数的开头有一个查询。

$bill = Doctrine::getTable('Bill')->find($request->getParameter('id'));

在我的doctrine模型中的class 'Bill.class.php'中,

前面有一个空行
<?php

因此,当类Bill被实例化时,新行被打印到屏幕上。

我只是想知道为什么php在发送zip Archive到浏览器时不给出像'headers already send'这样的错误信息。

0A是换行符。确保所有相关文件的<?php标记前没有换行符,?>标记后没有换行符(除非省略结束标记,这是推荐的)。
最有可能的罪魁祸首是下载操作的actions.class.php。

几天前我在symfony中遇到了完全相同的问题,问题是我的响应中有一个额外的字符(在我的实例中是一个空格)。而不是返回sfView::NONE;如果你在最后加一个骰子会怎么样?试试这个:

//make sure toolbar is disabled just to be extra safe
sfConfig::set('sf_web_debug', false);
$tmpFileName = tempnam("/tmp", "xb_");
$zip = new ZipArchive();
$zip->open($tmpFileName, ZipArchive::CREATE);
$zip->addFile('[directory_inside_webspace]/test.pdf', 'myTest.pdf');
$zip->close();
$this->getResponse()->clearHttpHeaders();
$this->getResponse()->setHttpHeader('Content-Type', 'application/zip');
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename=archive.zip');
// Unlock session in order to prevent php session warnings
$this->getUser()->shutdown();
// Send http headers to user client
$this->getResponse()->sendHttpHeaders();
echo file_get_contents($tmpFileName);
die;

我是这样做的:

// Unlock php session
$this->getUser()->shutdown();
// Send the response
$response->sendHttpHeaders();
$response->setContent(readfile(utf8_decode($tmpFileName)));
$response->sendContent();
return sfView::NONE;

可能是BOM错误

最新更新