Results 1 to 17 of 17

Thread: [RESOLVED] UTF8 and force download script

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    [RESOLVED] UTF8 and force download script

    I'm using this code to force download files:
    Code:
    switch( $file_extension )
    {
      case "pdf": $ctype="application/pdf"; break;
      case "exe": $ctype="application/octet-stream"; break;
      case "zip": $ctype="application/zip"; break;
      case "rar": $ctype="application/rar"; break;
      case "doc": $ctype="application/msword"; break;
      case "xls": $ctype="application/vnd.ms-excel"; break;
      case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
      case "gif": $ctype="image/gif"; break;
      case "png": $ctype="image/png"; break;
      case "jpeg":
      case "jpg": $ctype="image/jpg"; break;
      default: $ctype="application/force-download";
    }
    header("Pragma: public"); // required
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false); // required for certain browsers 
    header("Content-Type: $ctype; charset: UTF-8;");
    header("Content-Disposition: attachment; filename=".$ftitle.";" );
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($filename));
    readfile("$filename");
    exit();
    $ftitle is utf8 string that is retreived from mysql table, it is may be english, arabic ...etc depend on the filename field stored in that location.

    the problem is the name (that appear in save dialog) is ok when it is english, but when it is arabic it is appear with strange chars like ظٹط©

    I did try to use utf8_encode($ftitle) but the same problem.

    thank's in advance

  2. #2

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Note: the field ftitle is utf8 encoded in mysql table. and I did use mysql_query('set names utf8'); but the same problem
    Last edited by Visual Basic.Net; Aug 30th, 2009 at 08:50 AM.

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Still have no solution!

  4. #4
    Frenzied Member
    Join Date
    Apr 2009
    Location
    CA, USA
    Posts
    1,516

    Re: UTF8 and force download script

    You're not entitled to a solution.

    Anyway, no problems with this working in Firefox. But in IE I see your issue. Some Googling suggests that urlencode() will make IE work... and it does, but then that screws up Firefox. Well based on that, you could do some User Agent sniffing, but that's never a great idea. Let me see if I can't find a better, cross-browser solution...

    Btw, I'd also advise putting quotes around filename:
    Code:
    header("Content-Disposition: attachment; filename=\"".urlencode($ftitle)."\";" );
    If you don't have them, some browsers will cut off anything that comes after a whitespace. You may also want the file extension on filename, or the file the user saves won't have one.

    Edit: nope, can't find a cross-browser solution; on the contrary I've found evidence suggesting that there isn't an interoperable solution (at this time). But if someone else wants to prove me wrong, I welcome it.
    Last edited by SambaNeko; Jan 30th, 2010 at 08:09 PM.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Thank's alot SambaNeko, It solved, But another problem appeared!!

    when I upload a .rar file, and download it with the above force-download script, the resulted downloaded file is corrupt. while when downloading the same file directly (not through the script) it is downloaded successfully!

    That problem appeared only when I tested it on the server, while on localhost, it worked ok!

    I tried this http://w-shadow.com/blog/2007/08/12/...load-with-php/
    but the same problem, >=1MB rar files are always corrupted!!!

    Thank's in advance

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    if you see the comments in the above URL, there are also some people who have the same problem!
    I tried to reduce the chunk size but that dosn't solve the problem

    Thank's in advance

  7. #7
    Frenzied Member
    Join Date
    Apr 2009
    Location
    CA, USA
    Posts
    1,516

    Re: UTF8 and force download script

    In the full script, connection_aborted() is checked while reading the file; my guess is that your remote server is aborting while reading the file, while your localhost is not. You could check this by changing the while loop...
    Code:
    	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);
    	}
    ...to...
    Code:
    while(!feof($file) && $bytes_send<$new_length){
      if(!connection_aborted()){
        $buffer = fread($file, $chunksize);
        print($buffer);
        flush();
        $bytes_send += strlen($buffer);
      }else{
        die("Connection aborted: ".connection_status());
      }
    }
    If you get the "Connection aborted" message, what number do you get after the colon?
    Last edited by SambaNeko; Feb 2nd, 2010 at 01:14 PM.

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    But how the message will be displayed? as a messagebox or the download dialog will be closed, and the message will be printed in the browser?!
    I did change the code and tried to download the rar file again. but nothing happened, no messagebox nor text on the browser. and the downloading completed. The size of the downloaded file is correct 2.10MB. but when I opened the correct file and the corrupted one with a UTF8 text editor and saw that the first line is different, and the rest of the lines are same for some lines at the beginning, but after many lines, they became different again!

    Thank's alot SambaNeko

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    here is the full code I used:

    Code:
    <? ob_start(); ?>
    <?php
    session_start();
    echo '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >';
    error_reporting(0);
    if(trim($_SESSION['downloadid'])=="" or (isset($_SESSION['downloadid'])==false)) {
    exit;
    }
    include("dbconnect.php");
    $fileid=(int) $_SESSION['downloadid'];
    $_SESSION['downloadid']="";
    $mysqlresult=mysql_query("select * from file where id=".$fileid) or die("Error");
    $rnum = mysql_num_rows($mysqlresult);
    if($rnum<=0) {
    	echo "Not Exists";
    	exit;	
    }
    $fname = mysql_result($mysqlresult,0,'fname');
    $ftitle = mysql_result($mysqlresult,0,'ftitle');
    $fsize = mysql_result($mysqlresult,0,'fsize');
    $ftype = mysql_result($mysqlresult,0,'ftype');
    
    $filename="./SAVEDFILES/".$fname;
    $file_extension = strtolower(substr(strrchr($filename,"."),1));
    
    if ( ! file_exists( $filename ) ) 
    {
      exit;
    };
    $bbb = basename($filename);
    $nnn = substr($bbb,0,strpos($bbb,'.'));
    $filetts = substr($bbb,strpos($bbb,'.'));
    $ffffff = $nnn;
    
    //=======================================================
    function output_file($file, $name, $mime_type='')
    {
    if(!is_readable($file)) die('File not found or inaccessible!');
    
    $size = filesize($file);
    $name = rawurldecode($name);
    
    $known_mime_types=array(
    "pdf" => "application/pdf",
    "txt" => "text/plain",
    "html" => "text/html",
    "htm" => "text/html",
    "exe" => "application/octet-stream",
    "zip" => "application/zip",
    "doc" => "application/msword",
    "xls" => "application/vnd.ms-excel",
    "ppt" => "application/vnd.ms-powerpoint",
    "gif" => "image/gif",
    "png" => "image/png",
    "jpeg"=> "image/jpg",
    "jpg" => "image/jpg",
    "php" => "text/plain"
    );
    
    if($mime_type==''){
    $file_extension = strtolower(substr(strrchr($file,"."),1));
    if(array_key_exists($file_extension, $known_mime_types)){
    $mime_type=$known_mime_types[$file_extension];
    } else {
    $mime_type="application/force-download";
    };
    };
    
    @ob_end_clean(); 
    
    if(ini_get('zlib.output_compression'))
    ini_set('zlib.output_compression', 'Off');
    
    header('Content-Type: ' . $mime_type);
    header('Content-Disposition: attachment; filename="'.$name.'"');
    header("Content-Transfer-Encoding: binary");
    header('Accept-Ranges: bytes');
    
    header("Cache-control: private");
    header('Pragma: private');
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    
    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);
    }
    
    $chunksize = 1*(100*100); 
    $bytes_send = 0;
    if ($file = fopen($file, 'r'))
    {
    if(isset($_SERVER['HTTP_RANGE']))
    fseek($file, $range);
    
    while(!feof($file) && $bytes_send<$new_length){
      if(!connection_aborted()){
        $buffer = fread($file, $chunksize);
        print($buffer);
        flush();
        $bytes_send += strlen($buffer);
      }else{
        die("Connection aborted: ".connection_status());
      }
    }
    fclose($file);
    } else die('Error - can not open file.');
    
    die();
    } 
    
    set_time_limit(0); 
    $file_path=$filename;
    output_file($file_path, $ftitle);
    ?>
    <?php ob_flush(); ?>
    Thank's in advance

  10. #10
    PowerPoster
    Join Date
    Sep 2003
    Location
    Edmonton, AB, Canada
    Posts
    2,629

    Re: UTF8 and force download script

    you're using fopen() to read; make sure you force fopen to read binary files by appending 'b' to the second parameter (rb, wb, etc). this may or may not be causing you any problems.

    anddd, in the future, you should really try indenting. it can get really to read through a complex/long script with no indenting.

  11. #11

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Thank's alot kows, finally Solved!!!
    what do you mean by "indenting" ?

    last question plz: the downloading dialog box, appeared without progressbar. Just says for example "100Bytes Opened So Far...". I thought that

    header("Content-Length: ".$size);

    will solve the problem, but it didn't

    Thank's alot SambaNeko and kows.

  12. #12
    PowerPoster
    Join Date
    Sep 2003
    Location
    Edmonton, AB, Canada
    Posts
    2,629

    Re: UTF8 and force download script

    you know what an indent is when you're writing a paper or something, correct?

    indentation:
    PHP Code:
    <?php
      
    //indented because it's a "level up" from the php tag
      
      
    if( ... condition ...){

        
    //indented because it's a "level up" from the if block

        
    switch( ... ){

          case 
    1:
            
    //indented further
            
    break;

          default:
            
    //and again

        
    }

      }

      
    //back to first level
    ?>
    this makes things much easier to read. for example:
    PHP Code:
    <?php
    //indented because it's a "level up" from the php tag
      
    if( ... condition ...){

    //indented because it's a "level up" from the if block

    switch( ... ){

    case 
    1:
    //indented further
    break;

    default:
    //and again

    }

    }

    //back to first level
    ?>
    content-length should provide the browser with the correct size information, as long as your $size variable is not empty.

  13. #13

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Mr.kows, the first problem dosn't solved
    still some rar files downloaded corruptly through script, while correctly through direct downloading.

    I really tired with this code. It taked alot of time

    Here is the full code with intending:
    Code:
    <? ob_start(); ?>
    <?php
    	session_start();
    	echo '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >';
    	error_reporting(0);
    	if(trim($_SESSION['downloadid'])=="" or (isset($_SESSION['downloadid'])==false)) {
    		echo "You Can't access this page directly";
    		exit;
    	}
    	include("dbconnect.php");
    	$fileid=(int) $_SESSION['downloadid'];
    	$_SESSION['downloadid']="";
    	$mysqlresult=mysql_query("select * from file where id=".$fileid) or die("Error");
    	$rnum = mysql_num_rows($mysqlresult);
    	if($rnum<=0) {
    		echo "File Dosn't Exists";
    		exit;	
    	}
    	$fname = mysql_result($mysqlresult,0,'fname');
    	$ftitle = mysql_result($mysqlresult,0,'ftitle');
    	$fsize = mysql_result($mysqlresult,0,'fsize');
    	$ftype = mysql_result($mysqlresult,0,'ftype');
    
    	$filename="./SAVEDFILES/".$fname;
    	// addition by Jorg Weske
    	$file_extension = strtolower(substr(strrchr($filename,"."),1));
    
    	if ( ! file_exists( $filename ) ){
      		echo "<html><title>Error</title><body>Error: File Dosn't Exists</body></html>";
      		exit;
    	}
    	$bbb = basename($filename);
    	$nnn = substr($bbb,0,strpos($bbb,'.'));
    	$filetts = substr($bbb,strpos($bbb,'.'));
    	$ffffff = $nnn;
    
    //=======================================================
    	function output_file($file, $name, $mime_type=''){
    		if(!is_readable($file)) die('File not found or inaccessible!');
    		$size = filesize($file);
    		$name = rawurldecode($name);
    
    		$known_mime_types=array(
    		"pdf" => "application/pdf",
    		"txt" => "text/plain",
    		"html" => "text/html",
    		"htm" => "text/html",
    		"exe" => "application/octet-stream",
    		"zip" => "application/zip",
    		"doc" => "application/msword",
    		"xls" => "application/vnd.ms-excel",
    		"ppt" => "application/vnd.ms-powerpoint",
    		"gif" => "image/gif",
    		"png" => "image/png",
    		"jpeg"=> "image/jpg",
    		"jpg" => "image/jpg",
    		"php" => "text/plain"
    		);
    
    		if($mime_type==''){
    			$file_extension = strtolower(substr(strrchr($file,"."),1));
    			if(array_key_exists($file_extension, $known_mime_types)){
    				$mime_type=$known_mime_types[$file_extension];
    			}else{
    				$mime_type="application/force-download";
    			}
    		}
    
    		@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: ' . $mime_type);
    		header('Content-Disposition: attachment; filename="'.$name.'"');
    		header("Content-Transfer-Encoding: binary");
    		header('Accept-Ranges: bytes');
    
    		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);
    		}
    
    
    		$chunksize = 1*(10*10); //you may want to change this
    		$bytes_send = 0;
    		if ($file = fopen($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.');
    	} 
    
    	set_time_limit(0); 
    	$file_path=$filename;
    	output_file($file_path, $ftitle);
    ?>
    <?php ob_flush(); ?>

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Note:
    When I download the file directly from server it opened without any problem.
    when I download the file through script it downloaded with the same size but corruptly. I got the following error:
    This archive is either in unknown format or damaged. Unexpected end of archive.
    That when I opened the rar file directly through Winrar or through 7-Zip. but when I open the file through 7-Zip=>Open Archive ... it opened without any problem!

    It seems that the error is at the end of the file?!

    how can I solve this problem plz?

    Thank's in advance

  15. #15
    PowerPoster
    Join Date
    Sep 2003
    Location
    Edmonton, AB, Canada
    Posts
    2,629

    Re: UTF8 and force download script

    I'll try to take a look at this in more detail when I get a chance; that won't be until later tonight. in the meantime, if you would like, this comment on PHP.net looks like a better written version of what you're doing, and may have what you're missing. make a new file, try it out, and try to spot any differences between your script and it if you're simply intent on fixing your own iteration.

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    Thank's alot bro... I replaced the funtion I used with this one:

    Code:
    function dl_file_resumable($file, $filetitle111,$is_resume=TRUE)
    {
        if (!is_file($file))
        {
            die("<b>404 File not found!</b>");
        }
    
        //Gather relevent info about file
        $size = filesize($file);
        $fileinfo = pathinfo($file);
        
        //workaround for IE filename bug with multiple periods / multiple dots in filename
        //that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
        $filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ?
                      preg_replace('/\./', '%2e', $filetitle111, substr_count($filetitle111, '.') - 1) :
                      $filetitle111;
        
        $file_extension = strtolower($path_info['extension']);
    
        //This will set the Content-Type to the appropriate setting for the file
        switch($file_extension)
        {
            case 'exe': $ctype='application/octet-stream'; break;
            case 'zip': $ctype='application/zip'; break;
            case 'mp3': $ctype='audio/mpeg'; break;
            case 'mpg': $ctype='video/mpeg'; break;
            case 'avi': $ctype='video/x-msvideo'; break;
            default:    $ctype='application/force-download';
        }
    
        //check if http_range is sent by browser (or download manager)
        if($is_resume && isset($_SERVER['HTTP_RANGE']))
        {
            list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
    
            if ($size_unit == 'bytes')
            {
                //multiple ranges could be specified at the same time, but for simplicity only serve the first range
                //http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
                list($range, $extra_ranges) = explode(',', $range_orig, 2);
            }
            else
            {
                $range = '';
            }
        }
        else
        {
            $range = '';
        }
    
        //figure out download piece from range (if set)
        list($seek_start, $seek_end) = explode('-', $range, 2);
    
        //set start and end based on range (if set), else set defaults
        //also check for invalid ranges.
        $seek_end = (empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)),($size - 1));
        $seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);
    
        //add headers if resumable
        if ($is_resume)
        {
            //Only send partial content header if downloading a piece of the file (IE workaround)
            if ($seek_start > 0 || $seek_end < ($size - 1))
            {
                header('HTTP/1.1 206 Partial Content');
            }
    
            header('Accept-Ranges: bytes');
            header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size);
        }
    
        //headers for IE Bugs (is this necessary?)
        //header("Cache-Control: cache, must-revalidate");   
        //header("Pragma: public");
    
        header('Content-Type: ' . $ctype);
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: '.($seek_end - $seek_start + 1));
    
        //open the file
        $fp = fopen($file, 'rb');
        //seek to start of missing part
        fseek($fp, $seek_start);
    
        //start buffered download
        while(!feof($fp))
        {
            //reset time limit for big files
            set_time_limit(0);
            print(fread($fp, 1024*8));
            flush();
            ob_flush();
        }
    
        fclose($fp);
        exit;
    }
    The progressbar appeared, but the 1st problem still there, even worse. Files are totally corrupted, and I can't open them even as Archive!

    Thank's alot for helping me

  17. #17

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: UTF8 and force download script

    The problem solved by changing the encoding of the file from UTF-8 to "system default"!!!
    Thank's alot for all

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width