Возвращение изображения base64 без утечки памяти ASP.NET MVC 3

77
7

У меня есть некоторые изображения, хранящиеся в базе данных в виде строк base64, и их нужно вернуть из контроллера MVC. Как я могу это сделать без утечки памяти?


Раньше я использовал это:


return File(Convert.FromBase64String(pictureString), "image/jpeg");

Однако процесс w3wp начинает использовать целую кучу памяти для нескольких фотографий.


Есть ли правильный способ сделать это? В настоящее время я решил просто установить каждое изображение на данные: image/jpg; base64, string_here, и он использует намного меньше памяти.. но, похоже, он намного медленнее загружает страницу.


Любая помощь приветствуется.

спросил(а) 2011-09-20T08:11:00+04:00 8 лет, 5 месяцев назад
1
Решение
49

+1 Комментарий Дарина Димитрова.


Если изображения /base 64 кодированные данные составляют более 85 КБ, они будут выделены на LOH (куча объектов). GC для таких распределений дороже из-за необходимости ждать генерации поколения 2.

Другой подход, если вам нужно использовать кодированные изображения base64, - это реализовать свой собственный поток, который считывает данные из кодированного значения Base64 в кусках, чтобы избежать выделения второго большого блока памяти. Если вы можете читать строку в chunck, вы также сможете избежать выделения объектов на LOH и потенциально просто повторно использовать реально небольшие буферы для чтения/декодирования.

ответил(а) 2011-09-20T09:28:00+04:00 8 лет, 5 месяцев назад
107

Раньше я использовал это:



В этом коде отсутствует утечка. Проблема в том, что он загружает все изображение в память, прежде чем передавать его в ответ. Память, которую вы наблюдаете в процессе w3p, нормальна, и как только коллекционер мусора выбьет его, он очистит его. Вы не должны беспокоиться об этом, если вы не показываете очень большие изображения.


Проблема с вашим дизайном заключается в том, что вы используете base64, что означает, что вам нужно загрузить все содержимое, прежде чем сможете его декодировать обратно в массив байтов. Другой подход состоял бы в том, чтобы сохранить изображения в виде исходных данных в вашей базе данных, а затем использовать потоки для чтения в кусках и сразу же записать эти фрагменты в ответ. Таким образом, только загружаемый в данный момент фрагмент загружается в память в определенный момент времени.

Еще один подход, который я могу вам предложить, - не хранить изображения в базе данных, а хранить их в файловой системе и сохранять только путь к изображению в базе данных. Тогда в действии вашего контроллера все, что вам нужно сделать, это return File(pathToTheImage, "image/jpeg").


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

ответил(а) 2011-09-20T09:22:00+04:00 8 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема