The reality is that your issue is related to the mess that is the Content-Disposition
header and more generally character encoding in HTTP headers. There is a very old Stack Overflow question: How to encode the filename parameter of Content-Disposition header in HTTP whose answers while dated cover a lot of what your issue is, but lets break it down.
The PhysicalFileResult
inherits from FileResult
and when being prepared for return to the client is processed by the FileResultExecutorBase
and the code you are interested from that class is contained in the SetContentDispositionHeader
method:
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();
}
}
Which ultimately lands you in the class ContentDispositionHeaderValue
from the Microsoft.Net.Http.Headers
namespace. There are currently 725 lines of code in this class most of which are there to ensure that the values returned are valid given the complicated nature of HTTP response headers.
RFC7230 specified that in the headers there is no useful encoding besides ASCII:
Historically, HTTP has allowed field content with text in the
ISO-8859-1 charset [ISO-8859-1], supporting other charsets only
through use of [RFC2047] encoding. In practice, most HTTP header field
values use only a subset of the US-ASCII charset [USASCII]. Newly
defined header fields SHOULD limit their field values to US-ASCII
octets. A recipient SHOULD treat other octets in field content
(obs-text) as opaque data.
Ultimately, some relief may be in sight as RFC8187 from September 2017 provides clarification which should alleviate some of this mess. Issue 2688 filed against HTTP Abstractions covers the need to incorporate this RFC into ASP.Net.
In the meantime you can try slugging an appropriately http encoded filename into the URI (http://example.com/filedownload/33/%F0%9F%98%80.png
) rather than relying upon the flawed Content-Disposition
header for filename suggestion. To be clear this is an incomplete fix and has the potential for not working on all clients.