views:

122

answers:

3

Following this question it was recommend that I should create a server side file that can return a file from the file system. How would I go about doing this in c# and .net. I imagine I pass the filename as a query string, this is read by the page and the file returned. Not really sure where to start on this from a codding point.

A: 

I would recommend reading the file in as a byte[] and sending it out with it's content-type and content-disposition set in the response and then just perform a response.binarywrite and a response.flush:

Byte[] bytes = null; 

try
{

    if(!FileExists(_filename)) return null;

    Byte[fs.Length] bytes 

    // get file contents
    using(System.IO.FileStream fs = System.IO.File.Open(_file, FileMode.Open, FileAccess.Read))
    {
        fs.Read(bytes, 0, fs.Length);
    }

}
catch(Exception ex)
{
            System.Text.ASCIIEncoding oEncoder = new System.Text.ASCIIEncoding();
            Byte[] bytes = oEncoder.GetBytes(ex.Message);

}

Context.Response.Buffer = false;
Context.ClearContent();
Context.ClearHeaders();
Context.ContentType = "application/octet-stream"; // Change this type as necessary
Context.AddHeader("Content-Length", bytes.Length.ToString());
Context.AddHeader("content-disposition", String.Format("inline; filename={0}", filename));
Context.Response.BinaryResult(bytes);
Context.Response.Flush();

The response portions will need adjusting according to your own delivery platform (separate page, in iframe, etc). You may not want to ClearHeaders() for instance.

Joel Etherton
What file type would you make this. .Net is not my main enviroment.
Rupert
@Rupert: I did mine in a web service initially, but this could be done with an aspx page with .cs code behind. If you put the file reading portion into a web service, you could then feed the byte array to any web page capable of consuming the service and the response.write could be done there.
Joel Etherton
When ever I have used web services in the past they returned XML (even when the return type was String). This is why I rulled this approach out.
Rupert
@Rupert: Yes, it's returned as XML, but the content of the data is still the byte representation of the binary data. Using BinaryWrite in the response will convert the byte array directly to the binary file again. I use this in a document server right now and can attest that it works for us flawlessly.
Joel Etherton
You could also use `Response.TransmitFile` to avoid buffering the contents in a `byte[]` array. http://msdn.microsoft.com/en-us/library/12s31dhy.aspx
LukeH
@Luke: tru dat, but TransmitFile fails for large files. Byte[] can be shunted out to the browser in chunks without timeouts and flushed when finished.
Joel Etherton
+4  A: 

You can use the Response.WriteFile method to send the contents of the file, though this may fail with larger files.

Be careful not to allow any filename to be specified in your query string, as users could then use this to access any file on your server. Better to have a database of files that are allowed with a name for each one, and look up a name supplied in the query string against this database to get the filename.

Mark_Carrington
`Response.TransmitFile` might be more useful for larger files. http://msdn.microsoft.com/en-us/library/12s31dhy.aspx
LukeH
A: 

This thread has my suggestion for serving files outside the web root. It uses a buffer to keep memory usage down.

Ray