There are a few topics that most web developers don't really get good exposure to early in their career. One of these topics is http headers. There are certain tasks that are only really possible after developing a strong grasp on HTTP Headers and how they work.
Not only do HTTP Headers open up doors to certain browser behaviors, but I've found that learning them and troubleshooting them really solidifies an understanding of how the browser works and the http request/response model.
This is the first of a 2 part article series dealing with HTTP Headers. This first part focuses on Content-Type and Content-Disposition. The second part will talk more about Cache-Control and how cache headers are involved in browser/proxy cache.
Lets say you were tasked with writing some page which returned a file to a user. That is, the user clicks some link and then the user receives the file.
You might notice on some browsers that the file opens right in the browser, while in other browsers users get prompted to download the file. Why?
When a browser gets handed a response that is a file it has two options. It can either prompt the user to download the file (Save As Dialog), or it can try to embed the file in the browser (the file will open and the contents will visible in the browser).
Normally most browsers (including IE and Firefox) will look at the MIME type (the Content-Type http header) and if it's recognized, try to open/embed it in the browser. If the the browser doesn't recognize the MIME type of the content, then it will prompt the user with a Save File dialog and the user can choose to either save it to disk or open it with a program of her choice.
Your only way of changing this behavior (if you wanted to say prompt the user to download the file every time) is to use the Content-Disposition and Content-Type http headers. Content-Type tells the browser what kind of content it IS, Content-Disposition tells the browser how the content should be handled.
It's also of note that even if you don't explicitly set the Content-Type header (MIME type) your web server probably will probably serve it off as text/html.
Since HTTP Headers are pretty much invisible without the proper tools. I'd strongly recommend one of the following utilities.
If you prefer using FireFox I'd recommend you download and get familiar with Tamper Data, a FireFox extension. Otherwise I'd consider using HTTP Fiddler if you prefer working with IE. All the screen caps of http headers you see here will be from of Tamper Data.
Consider the following two cases. Lets say I write an http handler that serves off content and I write it like so (below). What really happens?
Well the file Lipsum.txt which is just a text file gets pulled off the disk and returned for the http request. What do the http headers look like?
Notice how there's a Content-Type header which is "text/html"? This is because we didn't specify a content type and so IIS 6 defaulted to using the "Content-Type: text/plain" http header. Also notice that there is no Content-Disposition header. That is we are not explicitly telling the browser how to handle this content.
Because the browser gets a Content-Type of "text/html" (and it knows how to display such content) it simply displays it in the browser.
If we change the content type we can change the behavior. Lets assume we changed the content type to a PowerPoint (.ppt) document but still served up the same file (Lipsum.txt).
If we explicitly set a Content-Type then the browser will handle the document quite differently. Since the browser doesn't know how to display a PowerPoint document it prompts the user to use the OS to either save the document or open it in a program that supports the given Content Type.
context.Response.ContentType = "application/vnd.ms-powerpoint";
A fairly complete list of content types maintained by W3Schools can be found here.
So Content-Type allows us to tell the browser what kind of content we're handing it and it can behave accordingly. But what if we wanted to tell the browser how to handle content. Content-Disposition allows us to name the file that comes down over the wire and tell the browser to either whether to try and embed it in the browser, or to prompt the user to save the document to disk/open it in another program.
Before when Lipsum.txt was offered up with a Content-Type of text/html it was embedded in the browser (see above). What if we wanted to instead prompt the user to save the content to disk even if the browser is capable of displaying it? And what if we wanted to name the file as it came down instead of having it be the name of the .aspx/.ashx file serving it off like the screen cap above (FileHandler.ashx)?
context.Response.ContentType = "text/plain";
In the example above we set a Content-Disposition to "attachment" which specifies that the file should be downloaded as opposed to embedded in the browser. If we wanted it to be shown in the browser we would have set it to "inline". We also named the file coming over the wire by setting the "filename" property. We got the behavior from the screen cap above because the http headers looked like so:
In this article we talked briefly about how browsers handle content. If you don't set a Content-Type then the web server will often set one for you, this is often "text/html".
If you don't set a Content-Disposition then the filename of the document will often default to the page serving the content. The browser will also try to open the document (if it recognizes the content type), otherwise it will prompt the user to download the content. The only way to set the file name of the file and how it should be handled is to set a Content-Disposition header.