Intereting Posts
Android – Анимируйте верхний вид ViewMargin / bottomMargin / etc в LinearLayout или RelativeLayout Как установить изображение из динамически динамически в андроид? Обнаружение активности запускается для результата Как отключить / включить диалоговые отрицательные положительные кнопки? Android Как читать свойства BLE Чтение с возможностью записи уведомляемых характеристик GATT Edittext изменяет размеры в ландшафтном режиме при появлении экранной панели DatePickerDialog onDateSet вызывается при повороте Как достичь следующего в Realm для Android BroadcastReceiver для CONNECTIVITY_ACTION всегда возвращает null в aim.getExtras () Обнаружение линии на музыкальном листе в Android Android – программный набор TextView TextStyle? Android: Как создать YouTube-подобные VR-элементы управления? Когда должен использоваться файл dimens.xml в Android? Правильное создание фрагмента в PopupWindow Разница между фрагментомTransaction.add и фрагментомTransaction.replace

Любой способ заставить браузер Android по умолчанию распознавать имена файлов, отличных от ASCII, в загрузках «Content-Disposition: attachment»?

Прежде всего, я уверен, что это не дубликат, потому что я довольно долго занимаюсь этой темой, как в 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.

Обновить

К сожалению, до сих пор я не получил ответа, который фактически решает проблему, упомянутую выше. Так щедрость истекает невостребованным. Пожалуйста, не отвечайте, если вы действительно не знаете, как кодировать неевропейские имена на смешанном языке таким образом, который распознается Android-браузером до ICS, или если у вас есть убедительные доказательства того, что это невозможно.

Solutions Collecting From Web of "Любой способ заставить браузер Android по умолчанию распознавать имена файлов, отличных от ASCII, в загрузках «Content-Disposition: attachment»?"

URLUtil.java отвечает за guessFileName которое вызывает parseContentDisposition которое использует это регулярное выражение "attachment;\\s*filename\\s*=\\s*(\"?)([^\"]*)\\1\\s*$" .

Для получения имени файла в соответствии с заголовком Content-Disposition.

Исходный код, ниже которого пытается воспроизвести функциональность parseContentDisposition, работает правильно, когда я его тестировал. Например, он возвращает файл 파일 フ ァ イ ル 名 .jpg.

 import java.util.regex.Matcher; import java.util.regex.Pattern; public class HelloWorld{ public static void main(String []args){ String contentDisposition = "Content-Disposition: attachment; " + " filename=" +"\"файла파일ファイル名.jpg\""; Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("attachment;\\s*filename\\s*=\\s*(\"?)([^\"]*)\\1\\s*$",Pattern.CASE_INSENSITIVE); try { Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition); if (m.find()) { System.out.println("Result: " + m.group(2)); } } catch (IllegalStateException ex) { // This function is defined as returning null when it can't parse the header } } } 

К сожалению, я не могу проверить это прямо сейчас, но я использую следующий код для отправки файла в браузер, и до сих пор у меня не было никаких проблем (даже с браузерами Android), надеюсь, что это может вам помочь:

  $formatRFC2231 = 'filename*=UTF-8\'\'%s'; $formatDef = 'filename="%s"'; switch ($useragent) { case "Opera": case "Firefox": $filename = rawurlencode($name); $format = $formatRFC2231; break; case "IE": case "Safari": case "Chrome": $filename = rawurlencode($name); $format = $formatDef; break; default: $filename = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $name); $format = $formatDef; break; } 

Ключевым моментом здесь является функция iconv, которая преобразует любой символ не-utf8 в ISO-8859-1

Я считаю, что вы столкнулись с ошибкой в ​​менеджере загрузки Android, как описано здесь:

https://code.google.com/p/chromium/issues/detail?id=162333