Вопрос

Я использую объект HttpContext, реализованный в дочернем элементе HttpHandler, для загрузки файла, когда у меня в имени файла есть символы, отличные от ascii, это выглядит странно в IE, тогда как в Firefox это выглядит нормально.

ниже приведен код:-

       context.Response.ContentType = ".cs";
context.Response.AppendHeader("Content-Length", data.Length.ToString());
context.Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}",filename));
        context.Response.OutputStream.Write(data, 0, data.Length);

context.Response.Flush();

когда я поставляю 'ß' 'ä' 'ö' 'ü' 'Ã3' 'ß' 'ä' 'ö' 'ü' 'Ã3' в поле Имя файла это выглядит по-другому, чем то, что у меня в имени файла это выглядит нормально в Firefox.добавление EncodingType и charset оказалось бесполезным.

В ie это '¡å''ä''ö''ü''ó''ß''ä''ö''ƒ⠼'_'ƒÂ3' а в firefox это 'АЙ' 'Яй' 'Яй' 'Яй' 'Яй' 'Яй' 'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'Яй'.

Есть идеи, как это можно исправить?

Это было полезно?

Решение

У меня была похожая проблема.Вы должны использовать HttpUtility.UrlEncode (URL-код) или Сервер.UrlEncode чтобы закодировать имя файла.Также я помню, что firefox в этом не нуждался.Более того, это испортило имя файла, когда оно закодировано в URL.Мой код:

// IE needs url encoding, FF doesn't support it, Google Chrome doesn't care
if (Request.Browser.IsBrowser ("IE"))
{
    fileName = Server.UrlEncode(fileName);
}

Response.Clear ();
Response.AddHeader ("content-disposition", String.Format ("attachment;filename=\"{0}\"", fileName));
Response.AddHeader ("Content-Length", data.Length.ToString (CultureInfo.InvariantCulture));
Response.ContentType = mimeType;
Response.BinaryWrite(data);

Редактировать

Я более внимательно прочитал спецификацию.Прежде всего RFC2183 заявляет , что:

Текущая грамматика [RFC 2045] ограничивает значения параметров (и, следовательно, имена файлов с размещением содержимого) US-ASCII.

Но затем я нашел ссылки на то, что [RFC 2045] является абсолютным, и нужно ссылаться RFC 2231, в котором говорится:

Звездочки ("*") используются повторно для обеспечения индикатора того, что язык и информация о наборе символов присутствуют и используется кодировка.Одна кавычка ("'") используется для разграничения набора символов и информации о языке в начале параметра значение.Знаки процента ("%") используются в качестве флага кодирования, который согласуется с RFC 2047.

Это означает, что вы можете использовать UrlEncode для символов, отличных от ascii, при условии, что вы включаете кодировку, указанную в rfc.Вот один из примеров:

string.Format("attachment; filename=\"{0}\"; filename*=UTF-8''{0}", Server.UrlEncode(fileName, Encoding.UTF8));

Обратите внимание , что filename входит в дополнение к filename* для обратной совместимости.Вы также можете выбрать другую кодировку и соответствующим образом изменить параметр, но UTF-8 охватывает все.

Другие советы

HttpUtility.UrlPathEncode может быть лучшим вариантом.Поскольку URLEncode заменит пробелы знаками '+'.

Для меня это решение работает во всех основных браузерах:

Response.AppendHeader("Content-Disposition", string.Format("attachment; filename*=UTF-8''{0}", HttpUtility.UrlPathEncode(fileName).Replace(",", "%2C"));
var mime = MimeMapping.GetMimeMapping(fileName);
return File(fileName, mime);

Используя ASP.NET MVC 3.

Замена необходима, потому что Chrome не любит запятую (,) в значениях параметров: http://www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/

Возможно, вы захотите прочитать RFC 6266 и посмотрите на тесты по адресу http://greenbytes.de/tech/tc2231/.

Для меня это решило проблему:

var result = new HttpResponseMessage(HttpStatusCode.OK)
{
   Content = new ByteArrayContent(data)
};

result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileNameStar = "foo-ä-€.html"
};

Когда я просматриваю repsonse в fiddler, я вижу, что имя файла автоматически было закодировано с использованием UTF-8:

Пример ответа скрипача с закодированным именем файла размещения содержимого с использованием UTF-8

Если мы посмотрим на значение заголовка Content-Disposition, мы увидим, что оно будет таким же, как у @Johannes Geyer в его ответе.Единственное отличие заключается в том, что нам не нужно было выполнять кодирование самостоятельно, об этом позаботится класс ContentDispositionHeaderValue.

Я использовал тестовые наборы для заголовка Content-Disposition на: http://greenbytes.de/tech/tc2231/ как упоминал Джулиан Решке.Информацию о классе ContentDispositionHeaderValue можно найти в MSDN.

Для Asp.Net Core (версия 2 на момент этого поста) UrlPathEncode устарел, вот как достичь желаемого результата:

System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
   FileName = Uri.EscapeUriString(fileName),
   Inline = true  // false = prompt the user for downloading;  true = browser to try to show the file inline
};

Response.Headers.Add("Content-Disposition", cd.ToString());

Я использую Uri.EscapeUriString for преобразует все символы в их шестнадцатеричное представление, и string.Normalize для нормализации Юникода форма C.(протестировано в ASP.NET MVC5 framework 4.5)

    var contentDispositionHeader = new System.Net.Mime.ContentDisposition
    {
        Inline = false,
        FileName = Uri.EscapeUriString(Path.GetFileName(pathFile)).Normalize()
    };
    Response.Headers.Add("Content-Disposition", contentDispositionHeader.ToString());
    string mimeType = MimeMapping.GetMimeMapping(Server.MapPath(pathFile));
    return File(file, mimeType);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top