Question

When downloading a file with HttpClient, I'm downloading first the headers and then the content. When headers are downloaded, I can see Headers collection on the Content property of HttpResponseMessage, but when accessing it through ContentDisposition on Headers, get null screenshot

Why this is happening? Fiddler shows headers are fine...

Code:

var responseMessage = await httpClient.GetAsync(uri, 
HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(continueOnCapturedContext: false);

Update 1

It looks like this class is following Content-Disposition implementation outlined in RFC 2616 and fails to handle Content-Disposition implementation update RFC 6266. RFC 2616 defines filename parameter value to be a quoted-string, where update RFC 6266 just states it should be value.

RFC 2616 Grammar

content-disposition = "Content-Disposition" ":"
                          disposition-type *( ";" disposition-parm )
    disposition-type = "attachment" | disp-extension-token
    disposition-parm = filename-parm | disp-extension-parm
    filename-parm = "filename" "=" quoted-string
    disp-extension-token = token
    disp-extension-parm = token "=" ( token | quoted-string )

RFC 6266 Grammar

content-disposition = "Content-Disposition" ":"
                        disposition-type *( ";" disposition-parm )

 disposition-type    = "inline" | "attachment" | disp-ext-type
                     ; case-insensitive
 disp-ext-type       = token

 disposition-parm    = filename-parm | disp-ext-parm

 filename-parm       = "filename" "=" value
                     | "filename*" "=" ext-value

 disp-ext-parm       = token "=" value
                     | ext-token "=" ext-value
 ext-token           = <the characters in token, followed by "*">

where ext-value = <ext-value, defined in [RFC5987], Section 3.2>

Examples

Working case

Working case

Failing case

Failing case

Update 2

Opened a ticket with MS connect.

Update 3

Microsoft has acknowledged that this is a bug and will fix it.

Was it helpful?

Solution

The problem is with the trailing ; in the content-disposition header

        [Fact]
        public void ParseContentDispositionHeader()
        {
            var value = ContentDispositionHeaderValue.Parse("attachment; filename=GeoIP2-City_20140107.tar.gz");
            Assert.Equal("GeoIP2-City_20140107.tar.gz",value.FileName);
        }

If I add the semi-colon the parsing will fail. If you look at the RFC6266 grammar, the semi-colon is only supposed to precede the parameter.

OTHER TIPS

Thank you - finding this definitely helped me. For the benefit of others, here is my workaround (as apparently this is still a thing today???)

I am in a somewhat controlled environment, so the following code assumes:

  • Only one Content-Disposition Header
  • The tag is in the format: inline; "filename";

This will reset the response's ContentDisposition header, so subsequent code works seamlessly:

<!-- language: c# -->
if (response.Content.Headers.ContentDisposition == null)
{
  IEnumerable<string> contentDisposition;
  if (response.Content.Headers.TryGetValues("Content-Disposition", out contentDisposition))
  {
   response.Content.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse(contentDisposition.ToArray()[0].TrimEnd(';').Replace("\"",""));
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top