by Derek Pinkerton
26. May 2006 16:17
I couple of weeks ago I started getting involved with the User Inteface team on the new version of QualTrax, which is due out later this year.
In order to ensure any documents stored in QualTrax are as secure as possible they will all be stored outside of the web-root. This means that they will not be accessible outside of QualTrax. There will not be a direct URL to go to any document. The documents can be stored anywhere on the server, or on an entirely different server. This also means that we have to come up with some alternative means of sending the file to the user. A common method of doing this in the past would be to copy the document into the web directories, and then remove it after a predetermined amount of time had passed. While this does work, it is not the most secure method available, and it requires you have a service running in the background to clean up these files periodically.
A good alternative for this is to use the ASP.Net Response.WriteBinary method to send your file to the browser. Here is an example of this:
C#
Response.Clear();
Response.Buffer = true;
Response.ContentType = @"application/pdf";
System.IO.FileStream myFileStream = new System.IO.FileStream("Filename.PDF", System.IO.FileMode.Open);
long FileSize = myFileStream.Length;
byte[] Buffer = new byte[(int)FileSize];
myFileStream.Read(Buffer, 0, (int)FileSize);
myFileStream.Close();
Response.BinaryWrite(Buffer);
Response.Flush();
Response.End();
This code is in an aspx page that I send in my document ID as the only parameter. So to bring up the document my url would look something like "showdocument.aspx?ID=XXX"
In a perfect world this would work as expected on all browsers, however we all know that this isn't a perfect world so as you might guess I had some problems with it. In particular Internet Explorer (who would have thought) has a problem with this. In researching this problem a co-worker (Vicky Herrala) came across this microsoft knowledgebase article, which points the blame at a script not returning a "content-length" header. We found that you can add this header by adding the following line to the code above.
Response.AddHeader("Content-Length", FileSize.ToString());
After adding this line, I tested again only to find that IE still had problems with this. Firefox renders it perfectly. ;) Looking into this further we found an msdn article that explains how IE decides how it should open the file. According to this article IE should be looking at "The server-supplied MIME type, if available." As you can see in the above snippet, we have specified the content type and yet IE still cannot render this document correctly. The msdn article also mentions that IE will examine the URL in an attempt to determine the content type. In order to fool Internet Explorer into realizing that this is in fact a PDF document I added a dummy parameter to my url that puts in a fake document name with the appropriate extension. My url now looks like "showdocument.aspx?ID=XXX&doc=test.pdf" I fired this up and was presented with my PDF!
I know there has to be a better way to do this so if anyone out there finds a suitable replacement please let me know, but as for now this is working.