Другие ответы копируют содержимое файла в память перед отправкой ответа. Если данные уже находятся в памяти, у вас будет две копии, что не очень хорошо для масштабируемости. Это может работать лучше вместо:
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();
}
Поскольку поток представляет собой набор байтов, нет необходимости использовать BinaryReader. И пока входной поток заканчивается в конце файла, вы можете просто использовать метод CopyTo () для потока, который вы хотите отправить в веб-браузер. Все содержимое будет записано в целевой поток без каких-либо промежуточных копий данных.
Если вам нужно скопировать только определенное количество байтов из потока, вы можете создать метод расширения, который добавляет еще пару перегрузок CopyTo ():
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;
}
}
}
Затем вы можете использовать его так:
inputStream.CopyTo(response.OutputStream, contentLength);
Это будет работать с любым входным потоком, но кратким примером будет чтение файла из файловой системы:
string filename = @"C:\dirs.txt";
using (FileStream fs = File.Open(filename, FileMode.Open))
{
SendFile(fs, fs.Length, "application/octet-stream", filename);
}
Как уже упоминалось ранее, убедитесь, что ваш тип MIME соответствует содержимому.