Copyright © 1999–2018 FastMail Pty Ltd
This is a technical post. Regular FastMail users subscribed to receive email updates from the FastMail blog can just ignore this post.
When you want to send a download file to a user based on a web request, it's well known you can just set the Content-Disposition header to attachment to get the browser to download the content and save it locally on the users machine. Additionally you can add a filename parameter to control the filename displayed to users.
Content-Disposition: attachment; filename="foo.txt"
The problem comes when the filename contains non-english (really non-ASCII characters). RFC2231 defines a way of adding character set encodings to MIME parameters. Unfortunately support for this RFC is scattered, and browsers have implemented various internal hacks/workarounds (eg. % URL encoded octets). The situation is sufficiently complicated that someone came up with a comprehensive set of tests and there's a good stackoverflow answer.
However looking over the test case examples, I realised that there appeared to be a solution that would work on all browsers except Safari quite well. The attwithfn2231utf8 test shows that all modern browsers except IE and Safari support the RFC2231 encoding. The attfnboth test shows that if you have a traditional filename parameter followed by a RFC2231 filename* parameter, IE and Safari pick the traditional parameter. The attwithfnrawpctenclong test shows that if you use % URL encoded octets in a traditional filename parameter, IE attempts to decode them as UTF-8 octets.
Putting that together, if you want to send a file called foo-ä.html, then setting a header of:
Content-Disposition: attachment; filename="foo-%c3%a4.html"; filename*=UTF-8''foo-%c3%a4.html
Will cause IE8+, Opera, Chrome, FF4+ (but not Safari) to correctly save a file named foo-ä.html. This should be easy to do with a URL escaping library that encodes UTF-8 octets not in the unreserved character set.