Browsers do not cache response sent by MediaView - cakephp

This is my controller code:
$this->viewClass = 'Media';
$params = array(
'id' => $filename '.gif',
'name' => $filename ,
'download' => false,
'extension' => 'gif',
'path' => $folderpath,
'cache' => '+30 days',
'modified' => '#' . filemtime($pathtofile),
);
$this->set($params);
and the response:
Debug is disabled in core.php. However, the browser (Firefox, Chrome) never caches the file and always download the whole thing. Is this because of the 200 OK response? How can I fix it?
EDIT
I probably should have added a sample of the actual request URL
http://localhost/mycontroller/mymediaaction/2345
I resolved the issue by setting the name attribute to the action parameter instead of the actual file name. I still appreciate an answer with some explanation of this behavior.

The following code snippet for a controller action would either serve a 304 response or the file. I think that the checkNotModified functionality should be done by the MediaView::render function internally, similar to the AssetDispatcher. But for the time being this snippet may be of help.
$modified = #filemtime(ROOT . $dir . $filename);
$this->response->modified($modified);
if ($this->response->checkNotModified($this->request))
{
$this->autoRender = false;
$this->response->send();
}
else
{
$this->viewClass = 'Media';
$params = array('id' => $filename,
'cache' => '+1 day',
'modified' => '#' . $modified, // Must be a string to work. See MediaView->render()
'path' => ROOT . $dir);
$this->set($params);
}
return;

Related

CakePHP issue when downloading csv file in safari on OS X

Following is the controller function that returns the csv file:
public function export(){
if ($this->request->is('get')) {
throw new MethodNotAllowedException();
}
$employee = $this->request->query['employee'];
$from = $this->request->query['from'];
$to = $this->request->query['to'];
$events = $this->Event->export($employee, $from, $to);
$this->response->download("export.csv");
$this->set(compact('events'));
$this->layout = 'ajax';
return;
}
Here is how I call it:
echo $this->Form->postLink(
$this->Html->image('export.png', array('width'=>'200px', 'height'=>'79px')),
array(
'controller' => 'events',
'action' => 'export',
'?' => array(
'employee'=>$_POST['data']['Event']['employee'],
'from'=>$_POST['data']['Event']['from'],
'to'=>$_POST['data']['Event']['to'],
'ext'=>'csv'
)
),
array('escape'=>false)
);
It is working all good on every platform and browser except from safari on OS X. After I try to download it on safari (only on OS X), the file is getting a .html extension.
Any help or guidance is much appreciated.

CakePHP/PHPUnit: Testing a redirect - Location header does not seem to be set correctly

When writing a cake php controller tests withing a mock object the Location header doesnt seem to be set. From looking at the code I know for a fact that redirect is being called with the correct value. What am I doing wrong here?
Login Code:
if (!$this->Auth->login()) {
...
echo "Redirect reached.\n";
$this->redirect('/users/login');
}
Test:
public function testLoginFailedRedirectsToLogin() {
$users = $this->generate('Users', array(
'components' => array('Session'=>array('setFlash'))));
$users->Session
->expects($this->once())
->method('setFlash');
$users->response
->expects($this->once())
->method('header')
->with('Location', '/users/login');
$data = array('Users' => array(
'username' => 'bad-user',
'password' => 'infinet',
'remember_me' => false,
));
$this->testAction('/users/login',
array('data' => $data, 'method' => 'post'));
var_dump($this->headers['Location']);
$this->assertEqual($this->headers['Location'], '/users/login');
}
Output:
Redirect reached.
string(74) "http://localhost/home/nishant/projects/atp/1/.build/tmp/27784/app/Console/"
...
1) LoginTest::testLoginFailedRedirectsToLogin
Failed asserting that two strings are equal.
--- Expected
+++ Actual
## ##
-'/users/login'
+'http://localhost/home/nishant/projects/atp/1/.build/tmp/27784/app/Console/
If I remove the assertEqual the redirect's expect fails as well.
Should be
return $this->redirect('/users/login');

Download function not working CakePHP

I read the documentation regarding file downloads, however I can't seem to get this to work.
I have read through questions here as well, and have had no luck.
My function looks as follows:
public function generate($id) {
$this->layout = 'ajax';
$this->Magazine->recursive = 2;
$DistributionLists = $this->Magazine->DistributionList->find('all',
array(
'conditions' => array(
'Magazine.id' => $id
),
'order' => array(
'DistributionList.priority ASC'
)
)
);
$this->set('magazine',$DistributionLists[0]['Magazine']['magazine_name']);
$this->set(compact('DistributionLists'));
}
public function download() {
$this->viewClass = 'Media';
$params = array(
'id' => "Magazine Distribution List.doc",
'name' => "Magazine Distribution List",
'download' => true,
'extension' => 'doc',
'path' => APP . "tmp" . DS
);
$this->set($params);
unlink(APP."tmp".DS);
$this->redirect(array('action'=>'index'));
}
public function afterFilter() {
parent::afterFilter();
if($this->action == 'generate') {
$this->redirect(array('action'=>'download'));
}
}
The reason I have an afterFilter function is because the word document that needs to be downloaded is created in the view file.
Does anyone know why this doesn't work?
You have to remove the call to the redirect method in your download method because it prevents your view from getting "rendered" due to the redirect.

CakePHP view file via Media Views doesn't work

I have CakePHP 1.3 and I have an action that is supposed to view a file, the file maybe a .pdf, .doc, .... or any document, but I get a blank page instead.
code sample:
public function view_attachments($attachment_id){
$attachment = $this->get_attachment($attachment_id);
if($attachment){
$path = pathinfo($attachment['EmailAttachment']['file']);
$this->view = 'Media';
$this->autoRender = false;
$params = array(
'id' => $path['basename'],
'name' => $path['filename'],
'download' => false,
'mimeType'=> $this->Common->get_mime_content_type($path['basename']),
'extension' => strtolower($path['extension']), // must be lower case
'path' => APP . $path['dirname'] . DS // don't forget terminal 'DS'
);
$this->set($params);
}
}
Any Ideas? Please advise.
check that media.ctp file must be blank... to get proper output...
Thanks
Checking on my own working code, the only difference I see is
$this->autoRender = false;
Of course your not supposed to have a "view_attachments.ctp" file.
Be aware that browser's can't open ".doc" natively. So even if you want him to display it, he will offer you to download it.
function download($id) {
$data = $this->OdmPieceJointe->read(null, $id);
$path = pathinfo($data['OdmPieceJointe']['fichier']);
$this->view = 'Media';
$params = array(
'id' => $path['basename'],
'name' => $path['filename'],
'download' => false,
'extension' => $path['extension'],
'path' => 'uploads/',
);
$this->set($params);
}
maybe :
Configure::write('debug', 0);

ie wont support dtds in feed cakephp

Ok I'm trying to create a rss feed with cakephp rss helper for some post of an app. I followed the cakephp book to the letter and it wont work with internet explorer... When I open it with Opera it work but with ie it says "Internet Explorer does not support feeds with DTDs."...
I know microsoft is not supporting dtds because a security thread but how can I fix this issue? The company where I work uses ie by standard so changing the browser is not an option...
here is the code... So you can see there is not a mayor modification in it...
default.ctp
echo $this->Rss->header();
if (!isset($documentData)) {
$documentData = array();
}
if (!isset($channelData)) {
$channelData = array();
}
if (!isset($channelData['title'])) {
$channelData['title'] = $title_for_layout;
}
$channel = $this->Rss->channel(array(), $channelData, $content_for_layout);
echo $this->Rss->document($documentData,$channel);
index.ctp
$this->set('documentData', array(
'xmlns:dc' => 'http://purl.org/dc/elements/1.1/'));
$this->set('channelData', array(
'title' => __("Most Recent Hitos", true),
'link' => $this->Html->url('/', true),
'description' => __("Most recent Hitos.", true),
'language' => 'en-us'));
foreach ($posts as $post) {
$postLink = array(
'controller' => 'soportes',
'action' => 'view',
$post['Soporte']['id']);
// You should import Sanitize
App::import('Sanitize');
// This is the part where we clean the body text for output as the description
// of the rss item, this needs to have only text to make sure the feed validates
$bodyText = preg_replace('=\(.*?\)=is', '', $post['Hito']['actividad']);
$bodyText = $this->Text->stripLinks($bodyText);
$bodyText = Sanitize::stripAll($bodyText);
$bodyText = $this->Text->truncate($bodyText, 400, array(
'ending' => '...',
'exact' => true,
'html' => true,
));
echo $this->Rss->item(array(), array(
'title' => $post['Hito']['actividad'],
'link' => $postLink,
'guid' => array('url' => $postLink, 'isPermaLink' => 'true'),
'description' => $bodyText,
'dc:creator' => $post['Hito']['user_id'],
'pubDate' => $post['Hito']['fecha_sugerida']));
}
On a very basic level it might be because of the debug level in core.php - cake outputs the render time I think - you could try setting Configure::write('debug', 0); in your controller action to see if it renders in IE? I've had issues with XML / RSS and IE due to this before.

Resources