Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpResponseMessage.Content.Headers ContentDisposition is null

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.

like image 494
Sean Feldman Avatar asked Jan 08 '14 23:01

Sean Feldman


2 Answers

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.

like image 73
Darrel Miller Avatar answered Sep 17 '22 08:09

Darrel Miller


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("\"",""));
  }
}
like image 22
alfgar Avatar answered Sep 18 '22 08:09

alfgar