Other responses copy the contents of the file into memory before sending the response. If the data is already in memory, then you will have two copies, which is not very good for scalability. This might work better:
public void SendFile(Stream inputStream, long contentLength, string mimeType, string fileName) { string clength = contentLength.ToString(CultureInfo.InvariantCulture); HttpResponse response = HttpContext.Current.Response; response.ContentType = mimeType; response.AddHeader("Content-Disposition", "attachment; filename=" + fileName); if (contentLength != -1) response.AddHeader("Content-Length", clength); response.ClearContent(); inputStream.CopyTo(response.OutputStream); response.OutputStream.Flush(); response.End(); }
Since Stream is a collection of bytes, there is no need to use BinaryReader. And while the input stream ends at the end of the file, you can simply use the CopyTo () method for the stream that you want to send to the web browser. All content will be written to the target stream without intermediate copies of data.
If you only need to copy a certain number of bytes from the stream, you can create an extension method that will add a few more CopyTo () overloads:
public static class Extensions { public static void CopyTo(this Stream inStream, Stream outStream, long length) { CopyTo(inStream, outStream, length, 4096); } public static void CopyTo(this Stream inStream, Stream outStream, long length, int blockSize) { byte[] buffer = new byte[blockSize]; long currentPosition = 0; while (true) { int read = inStream.Read(buffer, 0, blockSize); if (read == 0) break; long cPosition = currentPosition + read; if (cPosition > length) read = read - Convert.ToInt32(cPosition - length); outStream.Write(buffer, 0, read); currentPosition += read; if (currentPosition >= length) break; } } }
Then you can use it like this:
inputStream.CopyTo(response.OutputStream, contentLength);
This will work with any input stream, but a quick example is reading a file from the file system:
string filename = @"C:\dirs.txt"; using (FileStream fs = File.Open(filename, FileMode.Open)) { SendFile(fs, fs.Length, "application/octet-stream", filename); }
As mentioned earlier, make sure your MIME type is correct for the content.