0

download.php

} else {
    $filename = NULL;
}

$err = '<div align="center">GREEK error msg</div>';

if (!$filename) {
    // if variable $filename is NULL or false display the message
    echo $err;
} else {
    // define the path to your download folder plus assign the file name
    $path = '../downloads/'.$filename;

    // check that file exists and is readable
    if (file_exists($path) && is_readable($path)) {
        // get the file size and send the http headers
        $size = filesize($path);
        header('Content-Type: application/octet-stream;');
        header('Content-Length: '.$size);
        header('Content-Disposition: attachment; filename='.$filename);
        header('Content-Transfer-Encoding: binary');
        // open the file in binary read-only mode
        // display the error messages if the file can´t be opened
        $file = @ fopen($path, 'rb');
        if ($file) {
            // stream the file and exit the script when complete
            fpassthru($file);
            exit;
        } else {
            echo $err;
        }
    } else {
        echo $err;
    }
}
?>

and this is how I call it:

<a href="scripts/download.php?file=GREEKCHARS_Earth.pdf"></a>
  1. If file name is in English download script works ok.
    If file name is in Greek it shows the error msg.

  2. If I echo $filename I see the correct Greek name so I suppose that the correct name is passed in my download.php.

  3. Since I get the correct name with $filename and my actual file has the same name, where does the script fails to download my file and it gives me the error msg?

It seems that it fails to match the Greek $filename with the actual file.

Pavlos1316
  • 474
  • 10
  • 25
  • Try `header('Content-Disposition: attachment; filename='.rawurlencode($filename));` – Musa Nov 22 '12 at 06:03
  • There are many points at which this can screw up. First of all, is the value received correctly by the server? Try `bin2hex()`ing the `$_GET` value and check if those are the actual UTF-8 bytes for "ΔΨΞ" (`CE94CEA8CE9E`). – deceze Nov 22 '12 at 06:28
  • @deceze `echo bin2hex($_GET) . "
    ";` outputs nothing. `echo bin2hex($filename) . "
    ";` outputs: cea42ece942e5f3039385f
    – Pavlos1316 Nov 22 '12 at 06:38
  • And what is the string that produced `cea42ece942e5f3039385f`? – deceze Nov 22 '12 at 06:42
  • ok. **Τ.Δ._003_GammaRAE_II_R** output **cea42ece942e5f3030335f47616d6d615241455f49495f522e706466** – Pavlos1316 Nov 22 '12 at 06:47
  • @deceze can you think of anything else to test? thank you. – Pavlos1316 Nov 22 '12 at 07:04
  • Well, that's UTF-8, alright. It's only screwing up on the receiving end, as the name for the file? That says the client is misinterpreting the encoding of the filename, which is not terribly surprising since there's no indication whatsoever in the response what encoding is being used. I'm not sure, but maybe try adding `; charset=utf-8` to the `Content-Type` header? – deceze Nov 22 '12 at 07:07
  • @deceze **application/octet-stream; charset=utf-8;** if this is correct syntax then is not working either. – Pavlos1316 Nov 22 '12 at 07:15

1 Answers1

2

The problem is that HTTP headers may only contain ASCII characters. That's the standard, since the headers are there to define what content is following in what encoding, the headers themselves cannot contain characters in some yet-unspecified encoding.

To send non-ASCII symbols in the header, they need to be encoded according to RFC 2231.
See this answer here: How can I encode a filename in PHP according to RFC 2231?

Community
  • 1
  • 1
deceze
  • 510,633
  • 85
  • 743
  • 889
  • Hm.. I have never seen this. Can you explain me WHERE/HOW to use it? Thank you. – Pavlos1316 Nov 22 '12 at 07:30
  • When used the `bin2hex()` for `$filename` I got utf-8 result. But `` is sending the filename as **!#!#!#_EARTH.pdf** Is this something different? – Pavlos1316 Nov 22 '12 at 07:41
  • Instead of `Content-Disposition: attachment; filename=ΔΨΞ`, which is illegal according to the HTTP specs, you're supposed to send something like `Content-Disposition: attachment; filename=title*0*=utf-8...`. So just modify that line where you set the `header()`. – deceze Nov 22 '12 at 08:06
  • What do you mean exactly by "is sending the file name as..."? – deceze Nov 22 '12 at 08:06
  • Firebug shows the above url that has **file=GREEKCHARS_Earth.pdf** as **file=!#!#!#_EARTH.pdf** so I am asking if there is a php code that can be placed so the url gets the correct format. – Pavlos1316 Nov 22 '12 at 08:33
  • I'm pretty sure it does not show "!#!#". It's probably *URL encoded*, which looks like `%42%42...`. That's normal, since URLs cannot contain non-ASCII characters either. – deceze Nov 22 '12 at 08:46
  • oh ok... yes the #!#!#! was just my typing. is url encoded what it shows. – Pavlos1316 Nov 22 '12 at 08:48
  • Hi again. if I echo $filename (in my download.php) I get the correct greek name file. this means that the correct name is passed to my download.php Isn't it? If not it means is passing this: %CE%A4.%CE%94._003_GammaRAE_II_R.pdf Is there a way to decode this in my download.php and continue from there? Thank you – Pavlos1316 Nov 22 '12 at 10:45
  • "%CE%A4.%CE%94._..." is *URL encoding*. PHP will automatically decode this for all values in `$_GET` or `$_POST`. If you take the filename from there, you don't need to decode it. Otherwise: [`urldecode`](http://php.net/urldecode). – deceze Nov 22 '12 at 11:12
  • Then since my $filename is correct where does the download.php gets lost and doesn't find my file? – Pavlos1316 Nov 22 '12 at 11:16
  • I'm getting lost on what the problem is. Is it not finding the file? Is it not setting the filename correctly upon download? Both? Something else? If you're confused about the basics of encodings, a few articles on http://kunststube.net may help you get up to speed. – deceze Nov 22 '12 at 11:22