Intereting Posts
Какие альтернативы PlayN? JavascriptInterface в веб-браузере Android: несколько вызовов JS вызывают блокировку Редкое исключение NullPointerException в GoogleApiClient с использованием Firebase Эмулятор Visual Studio для Android. Для запуска эмулируемых устройств необходим внутренний виртуальный сетевой коммутатор Настройка Drawable в качестве цвета текста вызывает исключение. Значение цвета должно начинаться с # Android Canvas не рисовал Path, когда точка пути не видна Последовательный порт Android через аудиоразъем Улучшение синтаксического анализа Java / Kotlin JSON В чем разница между датчиками «гравитация» и «ускорение» в Android? Как работают кросс-платформенные платформы разработки мобильных приложений? Размер растрового изображения Android в xml Android Studio build.gradle – Не удается разрешить символ "android" Как получить отпечатки SHA1 из сертификата p12? Камера в Android, как получить лучший размер, размер предварительного просмотра, размер изображения, размер изображения, искаженное изображение Отображать огромные изображения в Android

Любой способ заставить браузер 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