Прежде всего, я уверен, что это не дубликат, потому что я довольно долгое время изучал эту тему, как в StackOverflow, так и в других местах. Аналогичные вопросы были заданы, но никто не получил удовлетворительного ответа.
Связанные (но не идентичные) вопросы из прошлого:
- браузер Android Chrome без необходимости переименовывает имена и типы загружаемых файлов
- Как закодировать параметр имени заголовка Content-Disposition в HTTP?
Я также полностью осведомлен о трюках mod_rewrite
, которые делают его совершенно ненужным для жонглирования имен файлов в HTTP-заголовках. Но предположим, что это не вариант.
Большинство современных браузеров (IE9 +, Firefox, Chrome) поддерживают RFC2231/5987 при загрузке файлов с не-ASCII-символами в своих именах. В таких случаях следующий PHP-код работает как шарм:
header("Content-Disposition: attachment; " .
"filename*=UTF-8''" . rawurlencode($filename));
IE <= 8 не понимает RFC2231/5987, но следующий код работает большую часть времени. Поскольку каждый браузер пытается каким-то образом эмулировать IE, это также работает во многих других браузерах, таких как Firefox.
header("Content-Disposition: attachment; " .
'filename="' . rawurlencode($filename) . '"');
Между тем, Chrome < 11 и Safari < 6, похоже, предпочитают следующее, несмотря на то, что он помещает не-ASCII-символы непосредственно в заголовок.
header("Content-Disposition: attachment; filename=" . $filename);
Пока все хорошо.
Но все разваливается, когда дело доходит до приложения браузера Android по умолчанию. (До сих пор я тестировал это в Gingerbread, Ice Cream Sandwich и Jelly Bean.)
Если вы даете ему стандартную обработку RFC2231/5987, браузер по умолчанию полностью игнорирует его и пытается угадать имя файла из последней части URL-адреса.
Если вы даете ему обычное нестандартное (IE <= 8) лечение, браузер по умолчанию пытается интерпретировать имя файла как ISO-8859-1, что приводит к неразборчивому беспорядку символов, или он молча отбрасывает все не-ASCII-символы. Точное поведение отличается от версий, но в любом случае понятно, что браузер по умолчанию для Android не был предназначен для поддержки формата rawurlencode().
То же самое происходит, если вы помещаете исходное имя файла в заголовок.
Обычно это не проблема с сторонними браузерами, такими как Firefox для Android, браузер Dolphin и браузер лодок. Браузерное приложение по умолчанию - единственное, что постоянно не понимает имена файлов UTF-8.
Возможно, это было окончательно исправлено в последней версии Android, или, возможно, оно будет исправлено в следующей версии. Но это не мой вопрос. Мне нужно это для работы на существующих устройствах, и есть еще миллионы устройств Gingerbread и ICS.
Я прочитал отчеты об ошибках, я прочитал жалобы, я прочитал почти все, что нужно прочитать об этой проблеме. До сих пор мне не удалось найти какую-либо схему кодирования, которая действительно работает.
Если кто-нибудь знает, как закодировать имя файла без имени ASCII ** (например, файла파일ファイル名.jpg
) в заголовке Content-Disposition
**, и узнайте его браузер по умолчанию Android, пожалуйста, поделитесь им! Меня не волнует, насколько он хакерский или нестандартный. Меня не волнует, нужно ли его настраивать для каждой версии Android.
Update
К сожалению, до сих пор я не получил ответа, который фактически решает проблему, упомянутую выше. Так щедрость истекает невостребованным. Пожалуйста, не отвечайте, если вы действительно не знаете, как кодировать неевропейские имена на смешанном языке таким образом, который распознается Android-браузером до ICS, или если у вас есть убедительные доказательства того, что это невозможно.