TIL: proper content-disposition to download files with UTF-8 names

This is not a question, but a post for anyone who may need it in the future. Sometimes some browsers may mangle the filename if it’s non-ASCII characters even if everything is in bloody UTF-8.

Picture worth a thousand words. Safari dowloands. Below: before. Above: after

The fix in its entirety:

file = "/path/to/your/file"

file_name = <get the name of the file if you want it to look nice>
file_extension = <file extension. For example, Path.extname(file)>
content_type = <MIME content type, e.g. text/plain etc.>

file_name_escaped = URI.encode(file_name)

conn
|> put_resp_content_type(content_type, "utf-8")
|> put_resp_header(
  "content-disposition",
  "attachment;filename=\"#{file_name}.#{file_extension}\";filename*=utf-8''#{file_name_escaped}.#{file_extension}"
)
|> send_file(200, user_book.file)

The actual fix is adding ;filename*=utf-8''<url-encoded file name>

Hope this helps someone

6 Likes