download αρχείων με ελληνικά ονόματα

Ήθελα πριν λίγο καιρό να ξεκινήσω ένα μικρό template για να συμπληρώνω κάποια σημεία και να δημιουργείται αυτόματα ένα word έγγραφο, ώστε να μπορώ στη συνέχεια να το τυπώσω όπου θέλω, να συνεχίσω να το επεξεργάζομαι και να το μορφοποιώ. Ξεκίνησα σαν χαρούμενος πληροφορικάριος και κλίκι-κλίκι, άρχισα να γράφω το template το έβαλα σε ένα χώρο, έφτιαξα και μία φόρμα στο web για να συμπληρώνεις τα 2-3 πραγματάκια που χρειάζονται και το τελικό συμπληρωμένο αρχείο το έστελνα για download. Tο δοκίμασα στον chrome που χρησιμοποιώ κυρίως και όλα ήταν μια χαρά. Ευτυχής είπα να το δοκιμάσω και σε Firefox και σε Internet Explorer. Εκεί ήταν που τελείωσε (τόσο σύντομα) το αίσθημα ευτυχίας και τη θέση του πήραν διάφορα κοσμητικά επίθετα. Ο Firefox αποθήκευε μεν το αρχείο με ελληνικά, αλλά δεν έπαιρνε όλο το όνομα, παρά μόνο ότι υπήρχε μέχρι το πρώτο κενό. Ο Internet Explorer έπαιρνε μεν όλο το όνομα, αλλά δεν διαβαζόταν γιατί τα ελληνικά είχαν χαλάσει γιατί τροποποιούσε το όνομα του αρχείου από utf8 encoding που ήταν σε ότι encoding ήθελε. Τελικά με λίγο ψάξιμο κατέληξα στο συμπέρασμα ότι ο κάθε browser έχει τα δικά του βίτσια όχι μόνο ως προς την κατανόηση, τη μορφοποίηση και την εμφάνιση του css, του html και του javascript κώδικα, αλλά ακόμα και στον τρόπο που πρέπει να δίνεις τα ονόματα των αρχείων που θέλεις να στείλεις σαν attachments για download. O κώδικας τελικά από αυτό (σε aspx):

void WriteFile(string filename, string data)
{
    this.Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8";
    this.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    this.Response.Write(data);
}

και αυτό (σε php):

function writeFile($filename, $data)
{
    header('content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8');
    header("Content-Disposition: attachment; filename=$filename;");
    echo $data;
}

Έγινε αυτό:

void WriteFile(string filename, string data)
{
    this.Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8";

    if (this.Request.Browser.Browser == "Firefox")
    {
        filename = filename.Replace(" ","%20");
        this.Response.AddHeader("Content-Disposition", "attachment; filename*=UTF8''" + filename);
    }
    else
    {
        filename = HttpUtility.UrlEncode(filename).Replace('+', ' ');
        this.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    }

    this.Response.Write(data);
}

και αυτό αντίστοιχα:

function writeFile($filename, $data)
{
    header('content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8');

    $agent = $_SERVER['HTTP_USER_AGENT'];
    if (strlen(strstr(strtolower($agent), 'firefox')) > 0) {
        $filename = str_replace(' ','%20',$filename);
        header("Content-Disposition: attachment; filename*=UTF8''$filename;");
    }
    else {
        $filename = str_replace('+',' ',urlencode($filename));
        header("Content-Disposition: attachment; filename=$filename;");
    }
    echo $data;
}

Με μερικές δοκιμές, μια λίγο πιο απλοποιημένη μορφή θα μπορούσε να είναι:

void WriteFile(string filename, string data)
{
    if (this.Request.Browser.Browser == "InternetExplorer")
    {
        filename = HttpUtility.UrlEncode(filename).Replace('+', ' ');
    }
    this.Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8";
    this.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
    this.Response.Write(data);
}

και

function writeFile($filename, $data)
{
    header('content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8');
    $agent = $_SERVER['HTTP_USER_AGENT'];
    if (strpos(strtolower($agent),'firefox') == false) {
        $filename = str_replace('+',' ',urlencode($filename));
}
header("Content-Disposition: attachment; filename=\"$filename\";");
echo $data;
}

Ώστε να στέλνει διαφορετικό header – ή διαφορετικά κωδικοποιημένο το όνομα – ανάλογα τον browser, σύμφωνα με τα ιδιαίτερα γούστα τους. Αυτό φυσικά δεν σημαίνει ότι άλλες εκδόσεις των browsers ή “περίεργοι” χαρακτήρες στα ονόματα δεν θέλουν περισσότερη εξειδικευμένη αντιμετώπιση. Όμως δεν έχω browsers – ούτε όρεξη προς το παρόν – να το ψάξω… Ίσως κάποια στιγμή αργότερα.

Δείτε το demo.