Media bestanden in een Kohana Module

Directory structuur

In de Kohana directory structuur gebruik ik een media directory die voor de hele applicatie toegankelijk is.

Indien er media wordt gebruikt in een Module e.g. '/modules/mijnmodule/media/*' kan deze niet direct benaderd worden door een path.

Dit wordt veroorzaakt door deze regel in het .htaccess bestand en willen we graag zo houden:

# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]

Je kan de media ook gewoon plaatsen in '/media' directory, maar dan valt de module uiteen in verschillende onderdelen.

De oplossing is door het path naar de media in de module directory na te bootsen d.m.v. een route in '/modules/mijnmodule/init.php' :

Route::set('mijnmodule_media', 'mijnmodule/media/',
    array('uri' => '(.*)+'))
    ->defaults(array(
        'controller' => 'mijnmodule_media',
        'action'     => 'index'
    ));

Vervolgens wordt in '/modules/mijnmodule/classes/controller/mijnmodule/media.php' het echte path naar de media opgevraagd en teruggestuurd naar de browers met de juiste headers:

Kohana 3.1 / 3.2
class Controller_Mijnmodule_Media extends Controller {

  public function action_index()
  {
    $uri = Request::current()->param('uri');

    $filename = DOCROOT.'modules/mijnmodule/media/' . $uri;

    if (!is_file($filename))
    {
      $this->request->status = 404;
    }
    else
    {
      $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

      $this->response->headers('Content-Type', File::mime_by_ext($extension));

      $this->response->headers('Content-length', filesize($filename));

      $this->response->body(file_get_contents($filename));
    }
  }

}
Kohana 3.0
class Controller_Mijnmodule_Media extends Controller {

  public function action_index() {

    $uri = Request::instance()->param('path_uri');

    $filename = DOCROOT.'modules/mijnmodule/media/' . $uri;

    if (!is_file($filename))
    {
      $this->request->status = 404;
    }
    else
    {
      $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

      $this->request->headers['Content-Type'] = File::mime_by_ext($extension);

      $this->request->headers['Content-length'] = filesize($filename);

      $this->request->send_headers();

      $fp = @ fopen($sFilename, 'rb');

      if ($fp) { 
        fpassthru($fp);
        exit; 
      }
    }
  }
}

Een alternatieve oplossing gevonden op Stack Overflow door het aanpassen van het .htaccess bestand:

# Protect application and system files from being viewed
RewriteCond %{REQUEST_URI} !^(.*/)*(application|application/cache|modules/[^/]*)/media/.*$
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]

Zie ook: Detecteren MIME type van een bestand