File Browser in CodeIgniter

This is a quick post. I’m going to show the code necessary to build a file browser in PHP using CodeIgniter. It allows file browsing in the server and opening files without leaving your app. Text files are displayed directly while other files are send to download.

Introduction

During a PHP project development cycle, we usually work locally, easily accessing our files. When we upload our work to an external server we need a way to verify our uploads, changes made by the app itself or check if an specific file has the correct version. Common ways of doing this are FTP or a file explorer like cPanels. But they need external tools. Other servers like PagodaBox, which is a Git server, have files updated through a ‘git push’.

To speed things up you can use the code presented in this post to check filed directly in the browser. There’s an obvious risk associated, so you need to guarantee the only the correct users access this functionality. This security layer is on your own. I’m not going to show any user control in this post.

There are other ways to integrate similar solutions in your application, but this is a simple working solution that can be improved according to your needs.

The Method

Considering that you have a controller only to administrative access, the following method is able to access your files.

    function file_browser()
    {
        $segment_array = $this->uri->segment_array();

        // first and second segments are the controller and method
        $controller = array_shift( $segment_array );
        $method = array_shift( $segment_array );

        // absolute path using additional segments
        $path_in_url = '';
        foreach ( $segment_array as $segment ) $path_in_url.= $segment.'/';
        $absolute_path = getcwd().'/'.$path_in_url;
        $absolute_path = rtrim( $absolute_path ,'/' );

        // check if it is a path or file
        if ( is_dir( $absolute_path ))
        {
            // link generation helper
            $this->load->helper('url');

            $dirs = array();
            $files = array();
            // fetching directory
            if ( $handle = @opendir( $absolute_path ))
            {
                while ( false !== ($file = readdir( $handle )))
                {
                    if (( $file != "." AND $file != ".." ))
                    {
                        if ( is_dir( $absolute_path.'/'.$file ))
                        {
                            $dirs[]['name'] = $file;
                        }
                        else
                        {
                            $files[]['name'] = $file;
                        }
                    }
                }
                closedir( $handle );
                sort( $dirs );
                sort( $files );

            }
            // parent folder
            // ensure it exists and is the first in array
            if ( $path_in_url != '' )
                array_unshift ( $dirs, array( 'name' => '..' ));

            // view data
            $data = array(
                'controller' => $controller,
                'method' => $method,
                'virtual_root' => getcwd(),
                'path_in_url' => $path_in_url,
                'dirs' => $dirs,
                'files' => $files,
                );
            $this->load->view( 'file_browser', $data );
        }
        else
        {
            // is it a file?
            if ( is_file($absolute_path) )
            {
                // open it
                header ('Cache-Control: no-store, no-cache, must-revalidate');
                header ('Cache-Control: pre-check=0, post-check=0, max-age=0');
                header ('Pragma: no-cache');

                $text_types = array(
                    'php', 'css', 'js', 'html', 'txt', 'htaccess', 'xml'
                    );
                $path_parts = pathinfo($absolute_path);
                // download necessary ?
                if( isset($path_parts['extension']) && in_array( $path_parts['extension'], $text_types) ) {
                    header('Content-Type: text/plain');
                } else {
                    header('Content-Type: application/x-download');
                    header('Content-Length: ' . filesize( $absolute_path ));
                    header('Content-Disposition: attachment; filename=' . basename( $absolute_path ));
                }

                @readfile( $absolute_path );
            }
            else
            {
                show_404();
            }
        }
    }

This code only work when the controller is inside /controllers. If you put it in a sub-folder you need to change the segments section. As it’s a simple logic, I think the comments are enough to explain it. Let’s got to the view.

View

The view is very simple as well..

    <h1>File Browser</h1>
    <h2><?php echo $virtual_root.'/'.$path_in_url ?></h2>
    <?php
        $prefix = $controller.'/'.$method.'/'.$path_in_url;
        if (!empty($dirs)) foreach( $dirs as $dir )
            echo '/'.anchor($prefix.$dir['name'], $dir['name']).'<br>';

        if (!empty($files)) foreach( $files as $file )
            echo anchor($prefix.$file['name'], $file['name']).'<br>';
    ?>

That’s all you need to finish your file browser. Now you can view your files without leaving your app.

References

A big part of the code was reused from here: https://github.com/EllisLab/CodeIgniter/wiki/simple-file-browser


  • Cesar

    Perfect. Full customizable for developers.
    Thks

  • Jules

    Thanks for the script!

    The problem is when I download a file from this browser it adds .html at the end of the file name and so I have to remove it to be able to open it.
    Do you know how to fix it ?

    • Hi,

      I have changed the script part where the download happens. To fix your problem just change this line:
      header(‘Content-Description: File Transfer’);

      With:
      header(‘Content-Type: application/x-download’);

      I updated the script to use pathinfo() because its better to control when the file has no extension.

      Cheers,
      Oscar

      • Jules

        Thanks !
        It works perfectly.

  • Swapnil Bhaisade

    Perfect.! But it also shows hidden system files. cant we fix it?

  • Swapnil Bhaisade

    cant restrict hidden system file even after editing extension array.
    can you help to hide system files?

    • oscardias

      Are you on a unix based system? If so you can do the following:

      while ( false !== ($file = readdir( $handle )))
      {
      // Check if file starts with a dot – indicates hidden files/folders
      if($file[0] == “.”)
      {
      continue;
      }

      if (( $file != “.” AND $file != “..” ))
      {
      if ( is_dir( $absolute_path.’/’.$file ))
      {
      $dirs[][‘name’] = $file;
      }
      else
      {
      $files[][‘name’] = $file;
      }
      }
      }

      • Swapnil Bhaisade

        nope i am working windows 7 only. i will let you know if works with windows environment