Я нашел решение, которое работает во всех установленных мной браузерах (IE8, FF16, Opera12, Chrome22).
Он основан на том факте, что браузеры ожидают значения в параметре имени файла, который кодируется в собственной кодировке браузера, если не указана [другая] кодировка.
Обычно нативная кодировка браузера - это utf-8 (FireFox, Opera, Chrome). Но исходная кодировка IE - Win-1250.
Так что, если мы поместим значение в параметр имени файла, который кодируется utf-8 / win-1250 в соответствии с браузером пользователя, это должно работать. По крайней мере, у меня это работает.
String fileName = "árvíztűrőtükörfúrógép.xls";
String userAgent = request.getHeader("user-agent");
boolean isInternetExplorer = (userAgent.indexOf("MSIE") > -1);
try {
byte[] fileNameBytes = fileName.getBytes((isInternetExplorer) ? ("windows-1250") : ("utf-8"));
String dispositionFileName = "";
for (byte b: fileNameBytes) dispositionFileName += (char)(b & 0xff);
String disposition = "attachment; filename=\"" + dispositionFileName + "\"";
response.setHeader("Content-disposition", disposition);
} catch(UnsupportedEncodingException ence) {
// ... handle exception ...
}
Конечно, это проверено только в браузерах, упомянутых выше, и я не могу на 100% гарантировать, что это будет работать в любом браузере все время.
Примечание № 1 (@fallen) :
Неправильно использовать метод URLEncoder.encode (). Несмотря на имя метода, он не кодирует строку в кодировку URL, но он кодирует в кодировку формы. (Кодирование форм довольно похоже на кодирование URL и во многих случаях дает одинаковые результаты. Но есть некоторые различия. Например, пробел '' кодируется по-другому: '+' вместо '% 20')
Для правильной строки в кодировке URL следует использовать класс URI:
URI uri = new URI(null, null, "árvíztűrőtükörfúrógép.xls", null);
System.out.println(uri.toASCIIString());