ASP.Net MVC: как отобразить изображение байтового массива из модели

116

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

Как я могу это сделать, не возвращаясь к базе данных?

Все решения, которые я вижу, используют ActionResultдля возврата к базе данных для получения изображения, но у меня уже есть изображение на модели ...

DK ALT
источник
11
Пожалуйста, перестаньте называть "ASP.NET MVC" просто "MVC". Один - это фреймворк, а другой - не зависящий от языка шаблон проектирования. Это как называть IE - «Интернет»
терешко
MVC Как отобразить изображение байтового массива из модели, когда оно равно нулю?
Chathz

Ответы:

214

Что-то вроде этого может сработать ...

@{
    var base64 = Convert.ToBase64String(Model.ByteArray);
    var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
}

<img src="@imgSrc" />

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

dav_i
источник
6
Следует отметить, что это встраивает изображение в HTML и позволяет обойти некоторые стандартные методы кэширования изображений.
Quintin Robinson
@QuintinRobinson Хоть уменьши количество запросов:)
dav_i
8
@dav_i Уменьшите количество начальных запросов. При оптимизации производительности сети невероятно важно понимать механику серверов, платформ промежуточного контента и клиентов, которые запрашивают и обрабатывают информацию. Я не хочу вдаваться в экстраординарные детали в комментарии, но хочу подчеркнуть необходимость по-настоящему понимать последствия использования такой техники.
Quintin Robinson
1
Ответ на вопрос может быть правильным, но я думаю, что проблема, которую мы пытаемся решить, имеет изъян. Если проблема заключается в предотвращении двух вызовов базы данных для получения данных, а затем второго для получения изображения, я думаю, что гораздо лучшим решением было бы использовать обработчик сортировки, который может реализовать кеширование для снижения общей нагрузки на сервер. Когда вы пытаетесь выяснить, почему ваше приложение «зависает» из-за того, что вы пытаетесь выгрузить огромный файл с использованием кодировки Base64 в поток ответов страницы, вы пожалеете, что не задумывались о более широкой картине.
Nick Bork
2
Отлично, я добавил в свою модель метод, чтобы использовать ее повторно: общедоступная строка GetBase64 () {var base64 = Convert.ToBase64String (ContentImage); return String.Format ("данные: изображение / gif; base64, {0}", base64); }
Родриго Лонго
40

Это сработало для меня

<img src="data:image;base64,@System.Convert.ToBase64String(Model.CategoryPicture.Content)" width="80" height="80"/>     
NoloMokgosi
источник
1
это тоже сработало для меня, любезно скажите, как отобразить изображение байтового массива из модели, когда оно равно нулю?
Chathz
Привет, Чатц, я предлагаю вам проверить модель в контроллере, прежде чем переходить к представлению. Если модель нулевая, передайте изображение по умолчанию
NoloMokgosi
26

Я рекомендую что-нибудь в этом роде, даже если изображение живет внутри вашей модели.

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

Образец модели:

[Bind(Exclude = "ID")]
public class Item
{
    [Key]
    [ScaffoldColumn(false)]
    public int ID { get; set; }

    public String Name { get; set; }

    public byte[] InternalImage { get; set; } //Stored as byte array in the database.
}

Пример метода в контроллере:

public async Task<ActionResult> RenderImage(int id)
{
    Item item = await db.Items.FindAsync(id);

    byte[] photoBack = item.InternalImage;

    return File(photoBack, "image/png");
}

Посмотреть

@model YourNameSpace.Models.Item

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
<h4>Item</h4>
<hr />
<dl class="dl-horizontal">
    <img src="@Url.Action("RenderImage", new { id = Model.ID})" />
</dl>
<dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Name)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.Name)
    </dd>
</dl>
</div>
Луи Бакаж
источник
2
Что такое «вернуть файл (...)»? Разве File не статический класс?
Бен Сьюардс,
3
Это должен быть объект FileContentResult ( msdn.microsoft.com/en-us/library/… )
Луи Бакаж
14

Один из способов - добавить это в новый класс C # или HtmlExtensions.

public static class HtmlExtensions
{
    public static MvcHtmlString Image(this HtmlHelper html, byte[] image)
    {
        var img = String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(image));
        return new MvcHtmlString("<img src='" + img + "' />");
    }
}

тогда вы можете сделать это в любом виде

@Html.Image(Model.ImgBytes)
Moji
источник
Мне это больше всего нравится - делает его чистым в Модели, а также в файле .cshtml. ЗДОРОВО!!
Кен
10

Если вы можете кодировать свои байты base-64, вы можете попробовать использовать результат в качестве источника изображения. В свою модель вы можете добавить что-то вроде:

public string ImageSource
{
    get
    {
        string mimeType = /* Get mime type somehow (e.g. "image/png") */;
        string base64 = Convert.ToBase64String(yourImageBytes);
        return string.Format("data:{0};base64,{1}", mimeType, base64);
    }
}

И на ваш взгляд:

<img ... src="@Model.ImageSource" />
Cᴏʀʏ
источник
5

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

Здесь много "если", так что есть большая вероятность, что это плохая идея:

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

// In your original controller action
HttpContext.Cache.Add("image-" + model.Id, model.ImageBytes, null,
    Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1),
    CacheItemPriority.Normal, null);

// In your view:
<img src="@Url.Action("GetImage", "MyControllerName", new{fooId = Model.Id})">

// In your controller:
[OutputCache(VaryByParam = "fooId", Duration = 60)]
public ActionResult GetImage(int fooId) {
    // Make sure you check for null as appropriate, re-pull from DB, etc.
    return File((byte[])HttpContext.Cache["image-" + fooId], "image/gif");
}

Это дает дополнительное преимущество (или это костыль?) Работы в старых браузерах, где встроенные изображения не работают в IE7 (или IE8, если размер превышает 32 КБ).

Джо Энос
источник
3

Это модифицированная версия ответа Маноджа, которую я использую в проекте. Просто обновил, чтобы взять класс, атрибуты html и использовать TagBuilder.

    public static IHtmlString Image(this HtmlHelper helper, byte[] image, string imgclass, 
                                     object htmlAttributes = null)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("class", imgclass);
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        var imageString = image != null ? Convert.ToBase64String(image) : "";
        var img = string.Format("data:image/jpg;base64,{0}", imageString);
        builder.MergeAttribute("src", img);

        return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
    }

Что затем можно использовать следующим образом:

    @Html.Image(Model.Image, "img-cls", new { width="200", height="200" })
AlexH
источник
3

В вашей БД должен быть байт [].

Мой байт [] находится в моем объекте Person:

public class Person
{
    public byte[] Image { get; set; }
}


Вам нужно преобразовать ваш byte [] в строку. Итак, у меня в контроллере:

String img = Convert.ToBase64String(person.Image);


Затем в моем файле .cshtml моя модель является ViewModel. Вот что у меня есть:

 public String Image { get; set; }


Я использую это в своем файле .cshtml так:

<img src="@String.Format("data:image/jpg;base64,{0}", Model.Image)" />

"data: изображение / расширение файла изображения ; base64, {0}, строка вашего изображения "

Желаю, чтобы это кому-то помогло!

Торп
источник
1

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

"data: image / [расширение типа файла изображения] ; base64, [здесь идет ваша строка base64] "

Вышеуказанное присвоено атрибуту imgтега src.

Единственная проблема с этим - слишком длинная строка base64. Поэтому я бы не рекомендовал его для отображения нескольких моделей в представлении.

Митч
источник
Вы поднимаете проблему и указываете сценарий варианта использования, не рекомендуя, но не предлагая решения для вашего сценария использования. Это сделало бы ваш ответ намного приятнее / полезнее и информативнее.
Кен
0

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

С моделью:

 public class Images
 {
    [Key]
    public int ImagesId { get; set; }
    [DisplayName("Image")]
    public Byte[] Pic1 { get; set; }
  }

Помощник:

public static IHtmlString GetBytes<TModel, TValue>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TValue>> expression, byte[] array, string Id)
    {
        TagBuilder tb = new TagBuilder("img");
        tb.MergeAttribute("id", Id);
        var base64 = Convert.ToBase64String(array);
        var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
        tb.MergeAttribute("src", imgSrc);
        return MvcHtmlString.Create(tb.ToString(TagRenderMode.SelfClosing));
    }

Представление получает объект: ICollection, поэтому вам нужно использовать его в представлении в инструкции foreach:

 @foreach (var item in Model)
  @Html.GetBytes(itemP1 => item.Pic1, item.Graphics, "Idtag")
}
Хосе Ортега
источник