Юникод в заголовке Content-Disposition - PullRequest
11 голосов
/ 30 марта 2010

Я использую объект 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();

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

В т. Е. Это 'ß' 'ä' 'ö' 'ü' 'ó' 'ß' 'ä '' ö '' ü '_' ó 'и в Firefox это' ß '' ä '' ö '' ü '' ó '' ß '' ä '' ö '' ü '' ó '.

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

Ответы [ 6 ]

17 голосов
/ 30 марта 2010

У меня была похожая проблема. Вы должны использовать HttpUtility.UrlEncode или Server.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] ограничивает значения параметров (и, следовательно, имена файлов Content-Disposition) 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 охватывает все.

7 голосов
/ 03 мая 2013

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

3 голосов
/ 16 июня 2015

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

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/

2 голосов
/ 20 октября 2017

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

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

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

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

Пример ответа Fiddler с закодированным именем файла Content-Disposition с использованием UTF-8

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

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

2 голосов
/ 02 мая 2012

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

0 голосов
/ 26 апреля 2018

Для 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());
...