Idiot-proof, cross-browser force download in PHP

后端 未结 7 1277
借酒劲吻你
借酒劲吻你 2020-12-16 05:40

I\'m using forced download to download mostly zips and mp3s on site i did (http://pr1pad.kissyour.net) - to track downloads in google analytics, in database and to hide real

7条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-16 06:31

    So, I used this code (It's modified version of resumable http download found on internet)

    function _output_file($file, $path)
    {
        $size = filesize($path.$file);
    
        @ob_end_clean(); //turn off output buffering to decrease cpu usage
    
        // required for IE, otherwise Content-Disposition may be ignored
        if(ini_get('zlib.output_compression'))
        ini_set('zlib.output_compression', 'Off');
    
        header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename="'.basename($file).'"');
        header("Content-Transfer-Encoding: binary");
        header('Accept-Ranges: bytes');
    
        /* The three lines below basically make the 
        download non-cacheable */
        header("Cache-control: no-cache, pre-check=0, post-check=0");
        header("Cache-control: private");
        header('Pragma: private');
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    
        // multipart-download and download resuming support
        if(isset($_SERVER['HTTP_RANGE']))
        {
            list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
            list($range) = explode(",",$range,2);
            list($range, $range_end) = explode("-", $range);
            $range=intval($range);
            if(!$range_end) {
                $range_end=$size-1;
            } else {
                $range_end=intval($range_end);
            }
    
            $new_length = $range_end-$range+1;
            header("HTTP/1.1 206 Partial Content");
            header("Content-Length: $new_length");
            header("Content-Range: bytes $range-$range_end/$size");
        } else {
            $new_length=$size;
            header("Content-Length: ".$size);
        }
    
        /* output the file itself */
        $chunksize = 1*(1024*1024); //you may want to change this
        $bytes_send = 0;
        if ($file = fopen($path.$file, 'rb'))
        {
            if(isset($_SERVER['HTTP_RANGE']))
            fseek($file, $range);
    
            while
                (!feof($file) && 
                 (!connection_aborted()) && 
                 ($bytes_send<$new_length) )
            {
                $buffer = fread($file, $chunksize);
                print($buffer); //echo($buffer); // is also possible
                flush();
                $bytes_send += strlen($buffer);
            }
        fclose($file);
        } else die('Error - can not open file.');
    
    die();
    }
    

    and then in model:

    function download_file($filename){
        /*
            DOWNLOAD
        */
        $path = "datadirwithmyfiles/"; //directory
    
        //track analytics
    
        include('includes/Galvanize.php'); //great plugin
        $GA = new Galvanize('UA-XXXXXXX-7');
        $GA->trackPageView();
    
        $this->_output_file($filename, $path);
    
    }
    

    It works as expected in all mentiond browser on Win / MAC - so far, no problems with it.

提交回复
热议问题