Потоковый вывод ASP.NET: 1 один большой фрагмент против X меньших фрагментов?

Использование .NET 4.0, IIS 7.5 (Windows Server 2008 R2). Я хотел бы передать двоичный контент размером около 10 МБ. Содержимое уже находится в MemoryStream. Интересно, автоматически ли IIS7 разбивает выходной поток на куски. От клиента, получающего поток, есть ли разница между этими двумя подходами:

//#1: Output the entire stream in 1 single chunks
Response.OutputStream.Write(memoryStr.ToArray(), 0, (int) memoryStr.Length);
Response.Flush();

//#2: Output by 4K chunks
byte[] buffer = new byte[4096];
int byteReadCount;
while ((byteReadCount = memoryStr.Read(buffer, 0, buffer.Length)) > 0)
{
   Response.OutputStream.Write(buffer, 0, byteReadCount);
   Response.Flush();
}

Заранее благодарю за любую помощь.


Я не пробовал ваше второе предложение, передавая исходный поток данных. Поток памяти действительно был заполнен из потока ответа веб-запроса. Вот код,

HttpWebRequest webreq = (HttpWebRequest) WebRequest.Create(this._targetUri);
using (HttpWebResponse httpResponse = (HttpWebResponse)webreq.GetResponse())
{
   using (Stream responseStream = httpResponse.GetResponseStream())
   {
      byte[] buffer = new byte[4096];
      int byteReadCount = 0;
      MemoryStream memoryStr = new MemoryStream(4096);
      while ((byteReadCount = responseStream.Read(buffer, 0, buffer.Length)) > 0)
      {
         memoryStr.Write(buffer, 0, byteReadCount);
      }
      // ... etc ... //
   }
}

Как вы думаете, может ли он безопасно передать responseStream в Response.OutputStream.Write()? Если да, можете ли вы предложить экономичный способ сделать это? Как отправить ByteArray + точную длину потока в Response.OutputStream.Write()?


person Polymerase    schedule 13.05.2011    source источник
comment
Будете ли вы показывать этот контент более одного раза?   -  person Simon Mourier    schedule 13.05.2011


Ответы (1)


Второй вариант является лучшим, так как ToArray фактически создаст копию внутреннего массива, хранящегося в MemoryStream.

Но вы также можете предпочтительно использовать memoryStr.GetBuffer(), который вернет ссылку на этот внутренний массив. В этом случае вам нужно использовать свойство memoryStr.Length, потому что буфер, возвращаемый GetBuffer(), как правило, больше, чем сохраненные фактические данные (он выделяется фрагмент за фрагментом, а не байт за байтом).

Обратите внимание, что лучше всего передавать исходные данные в виде потока непосредственно в выходной поток ASP.NET вместо использования промежуточного потока MemoryStream. Это зависит от того, как вы получаете свои двоичные данные в первую очередь.

Другой вариант, если вы часто обслуживаете один и тот же контент, — сохранить этот MemoryStream в физический файл (используя FileStream) и использовать Response.TransmitFile для всех последующих запросов. Response.TransmitFile использует низкоуровневые уровни сокетов Windows, и нет ничего более быстрого для отправки файла.

person Simon Mourier    schedule 16.05.2011
comment
Большое спасибо, сэр, за ваш исчерпывающий ответ. Я применил ваш совет, используя memoryStr.GetBuffer(). Только что провел регрессионный тест, и он работал отлично. - person Polymerase; 18.05.2011