title: CakePHP - Saving and serving files outside of webroot
body: <p>Using Cake version 2.4.3 stable</p>
  
  <p>So I am having a time here, I have modified this plug in to save files to the app folder <a href="https://github.com/srs81/CakePHP-AjaxMultiUpload/" rel="nofollow">https://github.com/srs81/CakePHP-AjaxMultiUpload/</a></p>
  
  <p>The uploaded files are being saved to /public_html/app/files</p>
  
  <p>Now the strange thing is, when trying to serve these files to the view, I can read the file name, the file size, but not the file itself, image, pdf, etc. </p>
  
  <p>When I try to access the file via direct url, i get this error : </p>
  
  <p>Error: FilesController could not be found. </p>
  
  <p>How can it be that I can read the file name, the file size, but not the file itself?</p>
  
  <p>There is a need to save the files in the app folder. These files should be protected and therefore only be accessed by users who are logged into the application. I have tried to use cake send file response with no outcome. </p>
  
  <p>Edit : I guess the real question at hand here is how can I read files from APP . DS . 'files' ?</p>
  
  <p>View code : </p>
  
  <pre><code>    public function view ($model, $id, $edit=false) {
      $results = $this-&gt;listing ($model, $id);
  
      $directory = $results['directory'];
      $baseUrl = $results['baseUrl'];
      $files = $results['files'];
  
      $str = "&lt;dt&gt;" . __("Pictures") . "&lt;/dt&gt;\n&lt;dd&gt;";
      $count = 0;
      $webroot = Router::url("/") . "ajax_multi_upload";
      foreach ($files as $file) {
          $type = pathinfo($file, PATHINFO_EXTENSION);
          $filesize = $this-&gt;format_bytes (filesize ($file));
          $f = basename($file);
          $url = $baseUrl . "/$f";
          if ($edit) {
              $baseEncFile = base64_encode ($file);
              $delUrl = "$webroot/uploads/delete/$baseEncFile/";          
              $str .= "&lt;a href='$delUrl'&gt;&lt;img src='" . Router::url("/") . 
                  "ajax_multi_upload/img/delete.png' alt='Delete' /&gt;&lt;/a&gt; ";
          }
          $str .= "&lt;img src='$url' /&gt; ";
          $str .= "&lt;a href='$url'&gt;" . $f . "&lt;/a&gt; ($filesize)";
          $str .= "&lt;br /&gt;\n";
      }
      $str .= "&lt;/dd&gt;\n"; 
      return $str;
  
  }
  </code></pre>
  
  <p>And the upload / save </p>
  
  <pre><code>public function upload($dir=null) {
      // max file size in bytes
      $size = Configure::read ('AMU.filesizeMB');
      if (strlen($size) &lt; 1) $size = 20;
      $relPath = Configure::read ('AMU.directory');
      if (strlen($relPath) &lt; 1) $relPath = "files";
  
      $sizeLimit = $size * 1024 * 1024;
              $this-&gt;layout = "ajax";
          Configure::write('debug', 0);
      $directory = APP . DS . $relPath;
  
      if ($dir === null) {
          $this-&gt;set("result", "{\"error\":\"Upload controller was passed a null value.\"}");
          return;
      }
      // Replace underscores delimiter with slash
      $dir = str_replace ("___", "/", $dir);
      $dir = $directory . DS . "$dir/";
      if (!file_exists($dir)) {
          mkdir($dir, 0777, true);
      }
      $uploader = new qqFileUploader($this-&gt;allowedExtensions, 
          $sizeLimit);
      $result = $uploader-&gt;handleUpload($dir);
      $this-&gt;set("result", htmlspecialchars(json_encode($result), ENT_NOQUOTES));
  }
  </code></pre>
  
  <p>The only real change from the original plug in is changing WWWROOT to APP to make the switch. Saving works fine and lovely. But its just weird that I can read the file name, file size in the view no problem but cannot view an image, pdf, etc. </p>