text/plain as html in IE, and a workaround

August 14, 2005

text/plain as html in IE, and a workaround

God I hate Internet Explorer... Here's another case of Microsoft trying to be clever, but shooting itself in the foot and thwarting its users in the process.

If I have a document, say foo.txt, that is in fact a text document and should be rendered as such, I don't want Internet Explorer displaying it as HTML. I don't care if the contents look like HTML, I'm sending a mime type of text/plain, so you'd better respect that. But Internet Explorer will consistently render text/plain as text/html if the contents appear to be HTML.

I understand Microsoft's reasoning... sometimes web servers incorrectly send HTML as text/plain, so mime-type guesswork generally makes sense to prevent the user from getting a page full of HTML source code. But at least give me a way to force text/plain if that's what I want to send.

The problem I've had is my jenChat sample files... There are links to several text files containing source code for the various PHP and HTML files. Every now and again, I'd get an email saying one file in particular was empty—contents.txt. I'd load it up in Firefox, see that it wasn't, and send the complainant a direct link. But then yesterday I looked at it in IE for the first time, and realized the problem. Internet Explorer sees that the content is predominantly HTML and renders it as such. And since the only content is HTML markup, you see nothing but a blank page.

So the workaround is actually fairly simple... Force IE users to download the file or open it with the default viewer (usually notepad). To do this, I added an .htaccess file in my document root containing the following lines:

AddHandler plaintextifier .txt
Action plaintextifier /plaintextifier.php

This causes all txt documents to be handled by a php script named plaintextifier.php. Now for the script:

<?php
$filename = $_SERVER["DOCUMENT_ROOT"].$_SERVER["REQUEST_URI"];
$browser = $_SERVER['HTTP_USER_AGENT'];

header('Content-Type: text/plain');
header('Content-Length: '.filesize($filename));

//to verify that the browser is IE Win 5-6 and not another browser pretending
//to be, we use some regular expressions

if(preg_match('/MSIE ([56]\.[0-9]+).*Win/',$browser) && !preg_match('/amiga|gecko|opera|omniweb|linux|unix/i',$browser)){
//force a save/download dialog
header('Content-Disposition: attachment;filename="'. substr($filename, strrpos($filename, '/')+1).'"');
}

//output the file to the browser
readfile($filename);
?>

I saved this in the document root, and that's all it took. Now IE users get a open/save dialog box when they request a text file. Yet another crIEsis averted with a server-side hack.

Posted by jon at August 14, 2005 11:59 AM

Comments

A more elegant solution is to have you script serve file content as "text/html" but surrounded by XMP tag, which is similar to PRE tag but doesn't render HTML inside.

Posted by: Alex Rak at May 11, 2006 9:06 PM

I'm not quite sold on that idea... Although it would allow you to copy/paste from the browser, if you were to save the document (either from a link or from the page itself), you'd end up with a whole bunch of browser generated HTML surrounding the actual content.

The whole point of this workaround is to allow IE users to see and download a text document and use it as is. It's worth noting that even Microsoft no longer recommends the use of the proprietary <xmp> element.

Posted by: jon at May 12, 2006 7:07 AM