Internet explorer не расшифровывает utf-8 filename [duplicate]

Вероятно, вы хотите передать "a" в качестве аргумента режима.

with open("foo", "a") as f:
    f.write("cool beans...")

Существуют другие перестановки аргумента режима для обновления (+), усечения (w) и двоичного (b) режима, но начиная с только "a", это ваш лучший выбор.

458
задан bignose 1 May 2009 в 09:37
поделиться

16 ответов

Обсуждается это, включая ссылки на проверку браузера и обратную совместимость, в предлагаемом RFC 5987 , «Набор символов и кодирование языка для параметров протокола заголовка гипертекстового протокола (HTTP)».

RFC 2183 указывает, что такие заголовки должны кодироваться в соответствии с RFC 2184 , который был устареван RFC 2231 , охватываемый проект RFC выше.

81
ответ дан Charles 20 August 2018 в 14:29
поделиться

У нас была аналогичная проблема в веб-приложении, и в итоге я прочитал имя файла из HTML <input type="file"> и установил это в кодировке url в новом HTML <input type="hidden">. Конечно, нам пришлось удалить путь, подобный «C: \ fakepath», который возвращается некоторыми браузерами.

Конечно, это напрямую не отвечает на вопрос OP, но может быть решением для других.

-1
ответ дан Andrei I 20 August 2018 в 14:29
поделиться
  • 1
    Совершенно другая проблема. Вопрос о загрузке , ваш ответ о загрузке . – Oskar Berggren 25 February 2016 в 17:38

Я нашел решение, которое работает для всех моих браузеров (т. е. всех браузеров, которые я установил - IE8, FF16, Opera 12, Chrome 22).

Мое решение описано в другом потоке: g0] Java servlet download filename специальные символы

Мое решение основано на том, как браузеры пытаются считывать значение из параметра filename. Если в параметре filename (например, filename*=utf-8''test.xml) нет кодировки, браузеры ожидают, что это значение закодировано в собственной кодировке браузера.

Различные браузеры ожидают различной собственной кодировки. Обычно исходная кодировка браузера - utf-8 (FireFox, Opera, Chrome). Но исходная кодировка IE - Win-1250. [Я не знаю ничего о других браузерах.)

Следовательно, если мы поместим значение в параметр filename parametr, который закодирован utf-8 / win-1250 в соответствии с браузером пользователя, он должен работать , По крайней мере, это работает для меня.

Короче говоря, если у нас есть файл с именем omáčka.xml, для FireFox, Opera и Chrome я отвечу на этот заголовок (закодированный в utf-8):

Content-Disposition: attachment; filename="omáčka.xml"

, а для IE I отвечает этот заголовок (закодирован в win-1250):

Content-Disposition: attachment; filename="omáèka.jpg"

Пример Java - это в моем сообщении , о котором упоминалось выше.

16
ответ дан Community 20 August 2018 в 14:29
поделиться
  • 1
    Обратите внимание, что можно указать оба способа кодирования параметра имени файла и что они выглядят корректно работающими со старыми браузерами и новыми браузерами (в этом случае старыми являются MSIE8 и Safari). Проверьте attfnboth в отчете, указанном @AtifAziz. – Pablo Montilla 10 July 2012 в 21:43
  • 2
    CP 1250 не может быть «родной» кодировкой Windows. Я думаю, что вы получили 1250, потому что это была ваша система. В этом случае это означает, что Windows всегда использует локаль системы, и есть not хороший способ правильно закодировать файл, если вы не знаете, кто они и каково их типичное поведение. – Yongwei Wu 27 February 2013 в 07:30
  • 3
    Моя собственная кодировка IE - это GBK. – bronze man 4 December 2014 в 03:23

Я обычно кодирую URL-адрес (с% xx) именами файлов и, похоже, работает во всех браузерах. Возможно, вы захотите сделать некоторые тесты.

-2
ответ дан Dario Solera 20 August 2018 в 14:29
поделиться
  • 1
    Я тестировал несколько, и это не работает во всех браузерах, поэтому вопрос. :) – Atif Aziz 18 September 2008 в 16:31

Поместите имя файла в двойные кавычки. Решил проблему для меня. Например:

Content-Disposition: attachment; filename="My Report.doc"

http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download

8
ответ дан Dmitry Kaigorodov 20 August 2018 в 14:29
поделиться

Если вы используете бэкэнд nodejs, вы можете использовать следующий код, который я нашел здесь здесь

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" 
             + encodeRFC5987ValueChars(fileName);

function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            // so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}
5
ответ дан Emanuele Spatola 20 August 2018 в 14:29
поделиться
  • 1
    Лучше использовать encodeURI(str). В качестве примера с датами в имени файла: encodeURIComponent('"Kornél Kovács 1/1/2016') = & gt; «Kornél Kovács 1% 2F1% 2F2016» vs. encodeURI('"Kornél Kovács 1/1/2016') = & gt; «Kornél Kovács 1/1/2016» – gdibble 17 May 2016 в 18:13

В PHP это сделало это для меня (если имя файла закодировано в UTF8):

header('Content-Disposition: attachment;'
    . 'filename="' . addslashes(utf8_decode($filename)) . '";'
    . 'filename*=utf-8\'\'' . rawurlencode($filename));

Протестировано против IE8-11, Firefox и Chrome. Если браузер может интерпретировать filename * = utf-8 , он будет использовать версию имени файла UTF8, иначе он будет использовать декодированное имя файла. Если ваше имя файла содержит символы, которые не могут быть представлены в ISO-8859-1, вы можете использовать вместо этого iconv.

3
ответ дан Gustav 20 August 2018 в 14:29
поделиться
  • 1
    Хотя этот код может ответить на вопрос, предоставляя дополнительный контекст в отношении why и / или , как он отвечает на вопрос, значительно улучшит его долгосрочную ценность. Пожалуйста, отредактируйте свой ответ, чтобы добавить некоторые объяснения. – Toby Speight 20 May 2016 в 14:32
  • 2
    Whoa, ни один из вышеперечисленных ответов только для кода не был отменен или критичен подобным образом. Также я нашел, что why был достаточно хорошо ответил: IE не интерпретирует имя файла * = utf-8, но для него требуется версия файла ISO8859-1, которую предлагает этот скрипт. Только хотел дать ленивый рабочий простой код для PHP. – Gustav 22 May 2016 в 15:20
  • 3
    Я думаю, что это получило downvoted, потому что вопрос не зависит от языка, а о том, какие RFC придерживаются при реализации кодировки заголовка. Спасибо, однако, для этого ответа, для PHP, этот код заставил мои проблемы уйти. – j4k3 28 June 2016 в 06:49
  • 4
    Спасибо. Этот ответ, возможно, не отвечал строго на вопрос, но это именно то, что я искал, и помог мне решить проблему на Python. – Lyndsy Simon 7 July 2016 в 14:43
  • 5
    Я уверен, что этот код можно использовать как вектор атаки, если пользователь может управлять именем файла. – Antti Haapala 11 September 2016 в 21:35

Я использую следующие фрагменты кода для кодирования (предполагается, что имя_файла содержит имя файла и расширение файла, то есть: test.txt):


PHP:

if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
     header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $fileName ) . '"' );
}
else
{
     header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $fileName ) );
}

Java:

fileName = request.getHeader ( "user-agent" ).contains ( "MSIE" ) ? URLEncoder.encode ( fileName, "utf-8") : MimeUtility.encodeWord ( fileName );
response.setHeader ( "Content-disposition", "attachment; filename=\"" + fileName + "\"");
149
ответ дан Kornel 20 August 2018 в 14:29
поделиться
  • 1
    Попробуйте GetAttachment.aspx / fake_filename.doc? Id = 34 (хотя это может быть причуда Apache) – Kornel 31 December 2009 в 22:24
  • 2
    это фантастическое решение; действительно очень помог мне. Благодарю. – kristopolous 14 September 2011 в 21:24
  • 3
    Вы уверены, что это не должно быть rawurlencode в PHP? – mpen 18 September 2013 в 00:46
  • 4
    Я спустился по кроличьей тропе и попробовал некоторые другие решения; пытаясь вынюхивать правильный браузер и версию, чтобы правильно настроить заголовки, это слишком большой кошмар. Chrome был неправильно идентифицирован как Safari, который не ведет себя одинаково вообще (разрывы на запятых, если не закодированы правильно). Сохраните проблему, используйте это решение и, при необходимости, укажите URL. – mpen 19 September 2013 в 18:24
  • 5
    Правильно, он должен быть rawurlencode в PHP, по крайней мере, для заголовка filename*=, поскольку value-chars используется в ext-value RFC 6266- & gt; RFC 5987 (см. tools.ietf.org/html/rfc6266 # section-4.1 & amp; tools.ietf.org/html/rfc5987#section-3.2.1 ) не позволяет пространство без процента ускорения (filename=, с другой стороны , кажется, что он может позволить пространство, не ускользая, хотя здесь должен присутствовать только ASCII). Нет необходимости кодировать с полной строгостью rawurlencode, поэтому несколько символов могут быть неизображены: gist.github.com/brettz9/8752120 – Brett Zamir 1 February 2014 в 15:06
  • 6
    Метод /:id/:filename действительно прост и работает, спасибо! – Luca Steeb 15 November 2015 в 02:32
  • 7
    В тысячу раз «Да». Вы серьезно выиграете время с этим. Более того - некоторые браузеры Android будут выставлять игнорировать Content-Disposition и создавать очень интересные имена файлов (они будут сгенерированы с вашего пути). Таким образом, единственным решением для поддержания здравого смысла является установка Content-Disposition: attachment и передача имени файла в качестве последнего компонента пути: – Julik 29 May 2016 в 20:09

Я знаю, что это старый пост, но он по-прежнему очень важен. Я обнаружил, что современные браузеры поддерживают rfc5987, что позволяет кодировать utf-8, процент кодируется (кодируется по URL). Тогда Naïve file.txt становится:

Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt

Safari (5) не поддерживает это. Вместо этого вы должны использовать стандарт Safari для записи имени файла непосредственно в кодированном заголовке utf-8:

Content-Disposition: attachment; filename=Naïve file.txt

IE8 и более старые не поддерживают его, и вам нужно использовать стандарт IE для utf -8, процентное кодирование:

Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt

В ASP.Net я использую следующий код:

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.Browser.Browser == "Safari")
    contentDisposition = "attachment; filename=" + fileName;
else
    contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

Я протестировал выше, используя IE7, IE8, IE9, Chrome 13 , Opera 11, FF5, Safari 5.

Обновление ноября 2013:

Вот код, который я использую в настоящее время. Я все еще должен поддерживать IE8, поэтому я не могу избавиться от первой части. Оказывается, браузеры на Android используют встроенный менеджер загрузки Android, и он не может достоверно анализировать имена файлов стандартным способом.

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
    contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\"";
else
    contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

Вышеописанное теперь протестировано в IE7-11, Chrome 32, Opera 12 , FF25, Safari 6, используя это имя для загрузки: 你好 abcABCæøåÆØÅääüïëêîâéíóóúúññ½§! # ¤% & amp; () = `@ £ $ € {[]} +'¨ ^ ~ '-_,;. Txt

В IE7 он работает для некоторых персонажей, но не для всех. Но кто сейчас интересуется IE7?

Это функция, которую я использую для создания безопасных имен файлов для Android. Обратите внимание, что я не знаю, какие символы поддерживаются на Android, но что я проверял, что они работают наверняка:

private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
    char[] newFileName = fileName.ToCharArray();
    for (int i = 0; i < newFileName.Length; i++)
    {
        if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
            newFileName[i] = '_';
    }
    return new string(newFileName);
}

@TomZ: я тестировал в IE7 и IE8, и оказалось, что я сделал не нужно избегать апострофа (').

@Dave Van den Eynde: объединение двух имен файлов в одной строке, как в соответствии с RFC6266, за исключением Android и IE7 + 8, и я обновил код для отражения это. Спасибо за предложение.

@Thilo: Не знаю о GoodReader или любом другом не-браузере. Возможно, вам повезло с использованием подхода Android.

@Alex Жуковский: Я не знаю, почему, но, как обсуждалось в Connect , это не работает ужасно хорошо.

306
ответ дан Martin Ørding-Thomsen 20 August 2018 в 14:29
поделиться
  • 1
    Он больше не работает в Firefox 8. – Arantor 15 November 2011 в 01:01
  • 2
    Получил это для Mobile Safari (raw utf-8, как было предложено выше), но это не работает для GoodReader с того же устройства. Есть идеи? – Thilo 8 March 2012 в 10:15
  • 3
    IE7 и 8 также требуют, чтобы апострофы были экранированы: .Replace (& quot; '& quot ;, Uri.HexEscape (' \ '')) – TomZ 19 June 2012 в 19:55
  • 4
    Почему бы не объединить их, как Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt и пропустить браузерный обнюхивание? Будет ли это работать? – Dave Van den Eynde 8 November 2013 в 16:02
  • 5
    Добрые люди в fastmail нашли еще одно обходное решение: blog.fastmail.com/2011/06/24/download-non-english-filenames Content-Disposition: attachment; имя_файла = & Quot; foo-% C3% a4.html & Quot ;; filename * = UTF-8''foo-% c3% a4.html Указание имени файла дважды (один раз без префикса UTF-8 и один раз с) заставляет его работать в IE8-11, Edge, Chrome, Firefox и Safari ( похоже на сафари с фиксированным яблоком, поэтому он работает и сейчас) – wullinkm 26 August 2016 в 09:47

В ASP.NET Web API я кодирую имя файла:

public static class HttpRequestMessageExtensions
{
    public static HttpResponseMessage CreateFileResponse(this HttpRequestMessage request, byte[] data, string filename, string mediaType)
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream(data);
        stream.Position = 0;

        response.Content = new StreamContent(stream);

        response.Content.Headers.ContentType = 
            new MediaTypeHeaderValue(mediaType);

        // URL-Encode filename
        // Fixes behavior in IE, that filenames with non US-ASCII characters
        // stay correct (not "_utf-8_.......=_=").
        var encodedFilename = HttpUtility.UrlEncode(filename, Encoding.UTF8);

        response.Content.Headers.ContentDisposition =
            new ContentDispositionHeaderValue("attachment") { FileName = encodedFilename };
        return response;
    }
}

IE 9 Not fixed [/g0] IE 9 Fixed [/g1]

8
ответ дан martinoss 20 August 2018 в 14:29
поделиться

RFC 6266 описывает « Использование поля заголовка Content-Disposition в протоколе передачи гипертекста (HTTP) ». Цитата из этого:

6. Вопросы интернационализации

Параметр «filename*» (, раздел 4.3 ), используя кодировку, определенную в [ RFC5987 ], позволяет сервер для передачи символов вне набора символов ISO-8859-1, а также необязательно указать используемый язык.

И в разделе примеров :

Этот пример аналогичен приведенному выше, но добавляет параметр «filename» для совместимости с пользовательскими агентами, не реализующими RFC 5987 :

Content-Disposition: attachment;
                     filename="EURO rates";
                     filename*=utf-8''%e2%82%ac%20rates

Примечание. Те пользовательские агенты, которые не поддерживают кодировку RFC 5987 , игнорируют «filename*», когда это происходит после «filename».

In Приложение D также имеется длинный список предложений по повышению интероперабельности. Он также указывает на сайт, который сравнивает реализации . Текущие тесты с полным прохождением, подходящие для общих имен файлов, включают в себя:

  • attwithisofnplain : простое имя файла ISO-8859-1 с двойными кавычками и без кодирования. Для этого требуется имя файла, которое является ISO-8859-1 и не содержит знаков процента, по крайней мере, не перед шестнадцатеричными цифрами.
  • attfnboth : два параметра в порядке описано выше. Должен работать для большинства имен файлов в большинстве браузеров, хотя IE8 будет использовать параметр «filename».

Что RFC 5987 в свою очередь ссылается на RFC 2231 , который описывает фактический формат. 2231 в первую очередь предназначен для почты, а 5987 сообщает нам, какие части могут использоваться для заголовков HTTP. Не путайте это с заголовками MIME, используемыми внутри тела multipart/form-data HTTP , который определен, в частности, RFC 2388 ( раздел 4.4 )) и проект HTML 5 .

55
ответ дан MvG 20 August 2018 в 14:29
поделиться
  • 1
    У меня были проблемы с Сафари. При загрузке файлов с русскими именами были получены ошибочные и нечитаемые символы. Решение помогло. Но нам нужно отправить заголовок в одну строку (!!!). – evtuhovdo 15 July 2016 в 10:14
  • 2
    лучший ответ! благодаря – Albert Tobac 7 March 2018 в 13:52

В моем сценарии «download.php» (на основе этот блогпост и ] был указан следующий код:

$il1_filename = utf8_decode($filename);
$to_underscore = "\"\\#*;:|<>/?";
$safe_filename = strtr($il1_filename, $to_underscore, str_repeat("_", strlen($to_underscore)));

header("Content-Disposition: attachment; filename=\"$safe_filename\""
.( $safe_filename === $filename ? "" : "; filename*=UTF-8''".rawurlencode($filename) ));

Это использует стандартный способ filename = "...", если используются только iso-latin1 и «безопасные» символы; если нет, он добавляет имя файла * = UTF-8 '', закодированное по URL-адресу. Согласно этот конкретный тестовый пример , он должен работать от MSIE9 вверх, а также от недавних FF, Chrome, Safari; на более поздней версии MSIE, он должен предоставить имя файла, содержащее версию имени файла ISO8859-1, с символами подчеркивания на символах, не входящих в эту кодировку.

Окончательная заметка: макс. размер для каждого поля заголовка составляет 8190 байт на apache. UTF-8 может содержать до четырех байтов на символ; после rawurlencode это x3 = 12 байт на один символ. Довольно неэффективно, но теоретически теоретически возможно иметь более 600 «улыбок»% F0% 9F% 98% 81 в имени файла.

4
ответ дан renergy 20 August 2018 в 14:29
поделиться
  • 1
    ... но максимальная длина передаваемого файла также зависит от клиента. Просто выяснили, что самое большее [89 улыбок]. .Pdf имя файла проходит через MSIE11. В Firefox37 он не более [111x – renergy 5 April 2015 в 16:13

Я тестировал следующий код во всех основных браузерах, включая более старых Исследователей (через режим совместимости), и он хорошо работает везде:

$filename = $_GET['file']; //this string from $_GET is already decoded
if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE"))
  $filename = rawurlencode($filename);
header('Content-Disposition: attachment; filename="'.$filename.'"');
5
ответ дан Stano 20 August 2018 в 14:29
поделиться

в asp.net mvc2 я использую что-то вроде этого:

return File(
    tempFile
    , "application/octet-stream"
    , HttpUtility.UrlPathEncode(fileName)
    );

Я предполагаю, что если вы не используете mvc (2), вы можете просто закодировать имя файла, используя

HttpUtility.UrlPathEncode(fileName)
11
ответ дан Tim Cooper 20 August 2018 в 14:29
поделиться
  • 1
    Проблема решена, dev happy :-) – Serge Wautier 14 March 2011 в 10:24
  • 2
    Кодировка URL для кодирования имени файла недействительна, браузеру не следует расшифровывать их. – SerialSeb 28 April 2011 в 17:14
  • 3
    IE 11 определенно не декодирует кодировку url в этом поле. – pseudocoder 16 June 2015 в 15:50
  • 4
    Но он должен быть UrlEncoded, когда браузером является Chrome или IE, другие, такие как FF, Safari и Opera, работают отлично с отсутствием кодировки – RezaRahmati 9 March 2016 в 19:43
16
ответ дан Community 31 October 2018 в 10:54
поделиться
150
ответ дан Kornel 31 October 2018 в 10:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: