Реальность такова, что ваша проблема связана с беспорядком, который является заголовком Content-Disposition
и, в более общем смысле, с кодировкой символов в заголовках HTTP. Существует очень старый вопрос переполнения стека: Как закодировать параметр имени файла заголовка Content-Disposition в HTTP , ответы которого, хотя и датированные, охватывают большую часть вашей проблемы, но давайте разберем ее.
PhysicalFileResult
наследуется от FileResult
и при подготовке к возврату клиенту обрабатывается FileResultExecutorBase
, а интересующий вас код этого класса содержится в SetContentDispositionHeader
метод:
private static void SetContentDispositionHeader(ActionContext context, FileResult result)
{
if (!string.IsNullOrEmpty(result.FileDownloadName))
{
// From RFC 2183, Sec. 2.3:
// The sender may want to suggest a filename to be used if the entity is
// detached and stored in a separate file. If the receiving MUA writes
// the entity to a file, the suggested filename should be used as a
// basis for the actual filename, where possible.
var contentDisposition = new ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName(result.FileDownloadName);
context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
}
}
Что в конечном итоге приводит вас в класс ContentDispositionHeaderValue
из пространства имен Microsoft.Net.Http.Headers
. В этом классе в настоящее время 725 строк кода , большинство из которых существуют для того, чтобы гарантировать, что возвращаемые значения верны, учитывая сложную природу заголовков ответа HTTP.
RFC7230 указал, что в заголовках нет никакой полезной кодировки, кроме ASCII:
Исторически HTTP разрешал содержимое полей с текстом в
Кодировка ISO-8859-1 [ISO-8859-1], поддерживает только другие кодировки
путем использования кодировки [RFC2047]. На практике большинство полей заголовка HTTP
значения используют только подмножество кодировки US-ASCII [USASCII]. вновь
определенные поля заголовка ДОЛЖНЫ ограничивать значения их полей US-ASCII
октет. Получатель ДОЛЖЕН обрабатывать другие октеты в содержимом поля
(obs-text) как непрозрачные данные.
В конечном счете, может появиться некоторое облегчение, поскольку RFC8187 с сентября 2017 года дает разъяснения, которые должны смягчить некоторые из этих беспорядков. Выпуск 2688, поданный против абстракций HTTP покрывает необходимость включения этого RFC в ASP.Net.
В то же время вы можете попытаться вставить соответствующее имя в формате http в URI (http://example.com/filedownload/33/%F0%9F%98%80.png
), вместо того чтобы полагаться на некорректный заголовок Content-Disposition
для предложения имени файла. Чтобы было ясно, это неполное исправление, которое может работать не на всех клиентах.