Php – Web server serves up PDF file as wrong mime type

apache-2.2http-headersjoomlamime-typePHP

Following an upgrade to the latest version of Joomla, downloads from a website I am working on are being served incorrectly.

Example page: http://www.pacificpolicy.org/index.php?option=com_content&view=article&id=259:mic-paper&catid=39:rokfeature

They are being served up with the correct content-disposition on first visit, but any further visits PDF files are being loaded as text/html (i.e. displaying the file's contents on screen).

How can I force the browser to load the PDF correctly on each visit? My knowledge of PHP & http headers is pretty rudimentary, so I could use some help diagnosing this.

The host is a LAMP server, Joomla is 1.5.22, doc management plugin is Rubberdoc.

Response header on second visit reads:

Date: Thu, 16 Dec 2010 04:29:03 GMT
Server: Apache/XXx
X-Powered-By: PHP/xxx
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Etag: db71388c6fc952682ae2fd733d4b09c5
Content-Encoding: gzip
X-Content-Encoded-By: Joomla! 1.5
Expires: Mon, 1 Jan 2001 00:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Host
Last-Modified: Thu, 16 Dec 2010 04:29:03 GMT
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

And the download docs are called from a PHP file, which goes thusly:

<?php

// Check to ensure this file is included in Joomla!
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.view');

/**
 * HTML View class for the RubberDoc component
 *
 * @static
 * @package     Joomla
 * @subpackage  RubberDoc
 * @since 1.0
 */
class RubberDocViewDoc extends JView
{
    public function display($tpl = null)
    {
        global $mainframe, $option;

        $id = JRequest::getInt('id');


        if(!$id)
        {
            JError::raiseError(404, 'Page Not Found');
            return;
        }

        $model =& $this->getModel('doc');
        $model->hit();

        $data       =& $model->getData();
        $fileName   =& $data->get('file');
        $dirname    = $mainframe->getParams('com_rubberdoc')->get('rubberdoc_dir', 'rubberdoc');
        $filePath   = JPath::clean( JPATH_SITE.DS.$dirname.DS.$fileName );

        if( !JFile::exists( $filePath ) )
        {
            JError::raiseError(404, 'Page Not Found');
            return;
        }

        $fileName = $data->get('file');
        $extension = array_pop( explode('.', $fileName) );
        $fileName = $data->get('alias').'.'.$extension;
        $fileContent  = JFile::read( $filePath );
        $fileSize     = strlen($fileContent);
        require(JPATH_COMPONENT.DS.'helpers'.DS.'mime.mapping.php');
        $mime         = $mime_extension_map[$extension]; //application/octet-stream

        // required for IE, otherwise Content-disposition is ignored
        if(ini_get('zlib.output_compression'))  {
            ini_set('zlib.output_compression', 'Off');
        }

        $doc =& JFactory::getDocument();
        $doc->setMimeEncoding( $mime );
        $doc->setModifiedDate( $data->get('modified') );
        $doc->render();

        header('Content-Disposition: attachment; filename="'.$fileName.'" ');
        header('Content-Length: '. $fileSize);

        header('Pragma: public');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-Transfer-Encoding: binary');

        if( ! ini_get('safe_mode') ) { // set_time_limit doesn't work in safe mode
            @set_time_limit(0);
        }

        echo $fileContent;
    }
}

Thanks,
Nick
Port Vila, Vanuatu

Best Answer

It's hard to say for sure, but I would suspect that on the first visit they are being served by the java code, which sets the correct mime type. After that, there's likely some caching going on which is not setting the correct mime type. See if you have any PDF files floating around on disk. If so, you need to look at apache's configuration, not your code.

Related Topic