Каков самый быстрый способ передать изображение из FILESTREAM в SQL в браузер?

У меня есть изображения, хранящиеся в моей базе данных в FILESTREAM, и я пытаюсь найти лучшее решение для возврата этого изображения в веб-браузер.

Если бы я сам управлял файлами в файловой системе, самым быстрым способом было бы:

Response.TransmitFile(pathToFile);

Это не загружает файл в память перед его передачей обратно клиенту (насколько я понимаю), и поэтому это приятно и быстро.

В настоящее время я использую Linq to SQL для получения FILESTREAM. Это предоставляет FILESTREAM как двоичный объект.

До сих пор это довольно уродливый способ сделать это:

Response.WriteBinary(fileStreamBinary.ToArray());

Будет ли мне лучше не возиться с Linq to SQL и делать что-то более непосредственно?

Я начинаю задаваться вопросом, почему я вообще заморачивался с FILESTREAM, а не занимался управлением файлами сам. Я уверен, что для этого была причина, не используя слово «подножка»!


person joshcomley    schedule 06.06.2009    source источник


Ответы (3)


Это не загружает файл в память перед его передачей обратно клиенту (насколько я понимаю), и поэтому это приятно и быстро.

Правильно, но не забудьте установить для Response.BufferOutput значение false, значение по умолчанию — true.

Будет ли мне лучше не возиться с Linq to SQL и делать что-то более непосредственно?

Если вы не хотите сначала загружать весь двоичный контент в память, тогда да. Вот пример потоковой передачи двоичных данных из база данных (наряду с включением функции возобновляемой загрузки).

Я начинаю задаваться вопросом, почему я вообще заморачивался с FILESTREAM, а не занимался управлением файлами самостоятельно.

Основным преимуществом является целостность данных с поддержкой транзакций и включением в резервные копии базы данных, поэтому вам не нужно беспокоиться о несоответствии между резервной копией базы данных и резервной копией файловой системы. Недостатком всегда была производительность, которую пытается преодолеть вся эта функция файлового потока. Хотя, если они в среднем меньше 1 МБ, согласно этот документ на самом деле быстрее сохраняется в базе данных, чем в файловой системе.

В Sql Server 2012 появится новая функция под названием FileTables, основанный на поддержке FileStream. По сути, он действует как представление базы данных каталога файловой системы, в котором файлы, добавленные в этот каталог, автоматически добавляются в базу данных. FileTable (это фиксированная таблица схемы, которая содержит двоичный столбец Filestream для файла, на который вы можете ссылаться из других таблиц. ). Это позволит вам получить путь к файлу, который вы можете передать своей функции Response.TransmitFile(...), но при этом по-прежнему пользоваться поддержкой sql Filestream.

person Michael    schedule 02.02.2012

Что об этом ?

byte[] buffer = new byte[bufferSize];
int nBytes;
while((nBytes = fileStreamBinary.Read(buffer, 0, bufferSize) != 0)
{
    Response.OutputStream.Write(buffer, 0, nBytes);
}

Таким образом, вы никогда не загрузите весь поток в память.

person Thomas Levesque    schedule 06.06.2009
comment
Хм, может быть, мы говорим о разных типах объектов Binary - Linq возвращает объект System.Data.Linq.Binary, у которого нет метода Read() :( - person joshcomley; 06.06.2009
comment
Извините, я неправильно понял ваш пример кода и подумал, что fileStreamBinary был потоком... Я не знаком с System.Data.Linq.Binary, но, похоже, он извлекает весь буфер сразу, поэтому вы не можете избежать загрузки это в памяти. Поэтому я боюсь, что код, который вы находите уродливым, - единственный способ... - person Thomas Levesque; 06.06.2009
comment
Похоже, мне, возможно, придется обойти Linq при использовании FILESTREAM. Кажется глупым, учитывая, что весь смысл FILESTREAM заключался в том, чтобы обеспечить сверхбыструю потоковую передачу прямо с диска! - person joshcomley; 06.06.2009
comment
Вероятно, вы можете сделать это, выполнив SqlCommand в DataContext.Connection и извлекая данные с помощью SqlDataReader.GetBytes. - person Thomas Levesque; 06.06.2009
comment
@ThomasLevesque SqlFileStream — это SqlType, предназначенный для чтения двоичных данных, хранящихся с использованием поддержки Filestream. - person Michael; 02.02.2012
comment
@ThomasLevesque: Просто это, вероятно, более оптимально (быстрее для больших файлов), чем SqlDataReader.GetBytes, или это не имеет большого значения? - person Michael; 03.02.2012
comment
@ Майкл, если честно, я понятия не имею, имеет ли это какое-то значение;) - person Thomas Levesque; 03.02.2012

В основном та же идея, что и у Томаса, но немного более подробная. Буферизация должна быть отключена, а данные периодически фиксируются/сбрасываются, чтобы избежать буферизации всех входящих данных перед их отправкой клиенту.

Я использую аналогичный код для потоковой передачи данных (в данном случае Pdf:s) из большого двоичного объекта в базе данных -> служба WCF (потоковая передача) -> клиент< /strong> (Браузер)

Это, вероятно, не лучший подход для небольших элементов, но он полезен для передачи данных, поступающих из какого-то потока.

Response.Clear();
Response.ContentType = "application/pdf";
Response.Buffer = false;

var buffer = new byte[BufferSize];
int bytesRead;
while ((bytesRead = inputStream.Read(buffer, 0, BufferSize)) != 0)
{
     if (!Response.IsClientConnected)
          break;

     Response.OutputStream.Write(buffer, 0, bytesRead);
     Response.Flush();
}
person Jakob Möllås    schedule 14.04.2011