I recently had a need to track files and images which were uploaded and for their urls to be secret. This meant that they couldn’t sit in a folder waiting to be found and had to be saved below the site root.
To get access to them I wanted to the check the user permissions followed by forcing download of all files (including images). Here are the steps I took to accomplish this…
For the sake of this page, my (fake) file urls are something like:
example.com/user/123/file/456.pdf
Update the urlmanager to rewrite files to my filemanager/view:
'user//file/.[a-z0-9]+' => 'filemanager/view',
Update the filemanager class’ actionView function:
public function actionView($id)
{
$file = $this->loadModel($id);
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers
//header("Content-Type: " . $file->mime_type);
header("Content-Disposition: attachment; filename=\"" . str_replace(" ", "-", preg_replace("@[^a-z0-9 ]@", "", strtolower($file->file_name))) . '.' . $file->file_extension . "\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize(Yii::app()->basePath . '/../../uploads/user_files/' . $file->file_id . '.' . $file->file_extension));
readfile(Yii::app()->basePath . '/../../uploads/user_files/' . $file->file_id . '.' . $file->file_extension);
exit();
}
I also of course required filemanager access to be strict:
public function accessRules()
{
return array(
array('allow',
'actions'=>array('view', 'create','delete'),
'users'=>array(),
'expression' => 'User::model()->hasRightsToFile()',
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
And that’s about it. Controlled and forced file download with rewritten file urls.
[carousel keywords=”yii” tag=”fetchit-21″]