Sep 17, 2014

Ketan Patel

Upload and Download PDF File in CakePHP

In this tutorial we'll learn about how to upload, view and download pdf file in CakePHP.In my previous post on Multiple Image upload in CakePHP you learn about the basics of file upload, in this post we'll see some more CakePHP concepts regarding the file upload.


Upload and Download PDF file in Cakephp



First of all we have to create a table to store the file details.So run the below SQL Query into your database in order to create the table called 'reports'.

CREATE TABLE reports (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(50),
    description TEXT,
    report VARCHAR(300),
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);

Now create one file called 'ReportsController.php' in your app/Controller folder and copy the below code.

<?php 
class ReportsController extends AppController{
  public $helpers=array('Html','Form');

  /*function to display all files details*/
  public function index() {
   $this->set('Reports', $this->Report->find('all'));
        }
  
  /*function to add file record into the database */
  public function add() {
        if ($this->request->is('post')) {
            $this->Report->create();
  if(empty($this->data['Report']['report']['name'])){
         unset($this->request->data['Report']['report']);
    }
   if(!empty($this->data['Report']['report']['name'])){
       $file=$this->data['Report']['report'];
       $file['name']=$this->sanitize($file['name']);
       $this->request->data['Report']['report'] = time().$file['name'];
      
                 if($this->Report->save($this->request->data)) {
       move_uploaded_file($file['tmp_name'], APP . 'outsidefiles' .DS. time().$file['name']);  
       $this->Session->setFlash(__('Your Report has been saved.'));
              return $this->redirect(array('action' => 'index'));
          }
     }
                  $this->Session->setFlash(__('Unable to add your Report.'));
        }
    }
 
} 
?>



The add function code is self explanatory. but two things to note here: the sanitize() function and  move_uploaded_file() file path.



When you deal with any file uploading,make sure to sanitize the uploaded file name because sometimes it causes major problems. Never trust on the user input. This sanitize() function will remove the extra characters (you can say bad characters) and replace them with dash(-). Here is the sanitize() function. Copy the below code into your ReportsController file.

function sanitize($string, $force_lowercase = true, $anal = false) {
    $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]","}", "\\", "|", ";", ":", "\"", "'", "&#8216;", "&#8217;", "&#8220;", "&#8221;", "&#8211;", "&#8212;","—", "–", ",", "<",">", "/", "?");
    $clean = trim(str_replace($strip, "", strip_tags($string)));
    $clean = preg_replace('/\s+/', "-", $clean);
    $clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
    return ($force_lowercase) ?
        (function_exists('mb_strtolower')) ?
            mb_strtolower($clean, 'UTF-8') :
            strtolower($clean) :
        $clean;
}

Regarding the move_uploaded_file path,you may wish to have a directory of files outside of the webroot to prevent users from direct linking them. So we have created one folder called 'outsidefiles' in app directory.


Now create model file called 'Report.php' in your app/Model folder. Copy the below code and paste into model file.


<?php 
class Report extends AppModel{
public $validate = array(
    'report' => array(
        'rule1' => array(
            'rule'    => array(
            'extension',array('pdf')),
            'message' => 'Please upload pdf file only'
         ),
        'rule2' => array(
            'rule'    => array('fileSize', '<=', '1MB'),
            'message' => 'File must be less than 1MB'
        )
    )
);
}
?>

Here we have added two rules for the file handling. One is file extension which is pdf and the other is fileSize which is less than or equal to 1MB.You can change this limit as per your requirement.

Now its time to create the view files.Create one folder called 'Posts' into your app/View directory.

Create file called 'index.ctp' into newly created folder 'Posts' and copy the below code. 
<h1>Reports</h1>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Description</th>
        <th>Report Name</th>
        <th>Created</th>
    </tr>
    <?php foreach ($Reports as $Report): ?>
    <tr>
        <td><?php echo $Report['Report']['id']; ?></td>
        <td><?php echo $Report['Report']['title']; ?></td>
        <td><?php echo $Report['Report']['description']; ?></td>
        <td><?php echo $Report['Report']['report']; ?></td>
        <td><?php echo $Report['Report']['created']; ?></td>
    </tr>
    <?php endforeach; ?>
    <?php unset($user); ?>
</table>

Create file called 'add.ctp' into newly created folder 'Posts' and copy the below code.
<h1>Add Report</h1>
<?php
echo $this->Form->create('Report',array('enctype'=>'multipart/form-data'));
echo $this->Form->input('title');
echo $this->Form->input('description');
echo $this->Form->input('report', array('type' => 'file'));
echo $this->Form->end('Save Report');
?>

Now go to http://yoursite.com/reports/add If you are working on localhost then go to  http://localhost/yourprojectname/reports/add  and add one Record. You can check the uploaded file will be stored into app\outsidefiles folder and the record will be inserted into the table as well.


Now we'll add code for the view and download the uploaded file.Open your index.ctp and made below changes.

Find line
<th>Created</th>

and add, below line just after that.

<th colspan="2">Actions</th>
Find line

<td><?php echo $Report['Report']['created']; ?></td>
 and add the below two links after that.

<td><?php echo $this->Html->link('View Details', array('controller' => 'reports', 'action' => 'view', $Report['Report']['id']));?></td>
<td><?php echo $this->Html->link('Download', array('controller' => 'reports', 'action' => 'viewdown', $Report['Report']['id'],true));?></td>


Open your ReportsController.php file and copy the below code.
public function view($id = null) {
        if (!$id) {
            throw new NotFoundException(__('Invalid Report'));
        }

        $Report = $this->Report->findById($id);
        if (!$Report) {
            throw new NotFoundException(__('Invalid Report'));
        }
        $this->set('Report', $Report);
    }
Now make one file called 'view.ctp' into Reports folder and copy the below code.

<h1>Title : <?php echo h($Report['Report']['title']); ?></h1>
<p><small>ID: <?php echo $Report['Report']['id']; ?></small></p>
<p><small>Description: <?php echo $Report['Report']['description']; ?></small></p>
<p><small>Created: <?php echo $Report['Report']['created']; ?></small></p>
<p><small>File Name:</small><?php echo h($Report['Report']['report']); ?></p>
<p><?php echo $this->Html->link('View File',array('controller' => 'reports','action' => 'viewdown',$Report['Report']['id'],false),array('target'=>'_blank'));?></p>

VIEW and DOWNLOAD Function


Copy the below function in your controller file. The name viewdown is given to understand its functionality easily.This function will either display or download the file depending on the $download parameter value.
public function viewdown($id=null,$download=false) {
     if($download){
      $download=true;
     }

     $files=$this->Report->findById($id);
      $filename=$files['Report']['report'];
      $name=explode('.',$filename);
     $this->viewClass = 'Media';
     
      // path will be app/outsidefiles/yourfilename.pdf
      $params = array(
            'id'        => $filename,
            'name'      => $name[0],
             'download'  => $download,
            'extension' => 'pdf',
            'path'      => APP . 'outsidefiles' . DS
        );
        
     $this->set($params);
    }


Thats it.!! Your demo is ready.Go to index page to view all the files details.Click on the download file to download it. Go to view page and click on the viewfile link to view the pdf file.

If you like this post then please share it to spread across the world.

Ketan Patel

About Ketan Patel -

I have developed a wide range of websites using CorePHP, Opencart, CakePHP and CodeIgniter including sites for startup companies and small businesses. Apart from my blogging life, I like to read Novels, Listening music and Net surfing.

Subscribe to this Blog via Email :