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


115

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

Як я можу це зробити, не повертаючись до Бази даних?

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


11
Перестаньте посилатися на "ASP.NET MVC" просто як "MVC". Один - це рамка, а інший - не залежно від мови. Це як дзвонити IE - "в Інтернет"
tereško

MVC Як відобразити зображення масиву байтів у моделі, коли вона є нульовою?
Chathz

Відповіді:


214

Щось подібне може спрацювати ...

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

<img src="@imgSrc" />

Як зазначено в коментарях нижче, будь ласка, використовуйте вищезгадане, озброєне тим, що, хоча це може відповісти на ваше питання, воно може не вирішити вашу проблему . Залежно від вашої проблеми це може бути рішенням, але я б не повністю виключав доступ до бази даних двічі.


6
Слід зазначити, що це вбудує зображення в HTML і обійде декілька стандартних методів кешування зображень.
Квінтін Робінсон

@QuintinRobinson Хоча зменшити кількість запитів:)
dav_i

8
@dav_i Зменшити кількість початкових запитів. Під час оптимізації веб-продуктивності неймовірно важливо зрозуміти механіку серверів, посередницьких платформ контенту та клієнтів, які запитують та обробляють інформацію. Я не хочу вдаватися до коментарів надзвичайних деталей, але хочу наголосити на необхідності по-справжньому зрозуміти наслідки використання такої методики.
Квінтін Робінсон

1
Відповідь може бути правильною для запитання, але я думаю, що проблема, яку ми намагаємося вирішити, має ваду. Якщо проблема в тому, що перешкоджає двом дзвінкам до бази даних, щоб отримати Дані, а потім секунді для отримання зображення, я думаю, що набагато кращим рішенням було б використовувати обробник сортування, який може реалізувати кешування для зменшення загального навантаження на сервер. Коли ви намагаєтеся з’ясувати, чому ваша програма захлинається, оскільки ви намагаєтеся скинути величезний файл, використовуючи кодування Base64, до потоку відповідей сторінки, ви хочете, щоб ви подумали більше про більшу картину.
Нік Борк

2
Чудово, я додав метод у свою модель, щоб знову використовувати його: public string GetBase64 () {var base64 = Convert.ToBase64String (ContentImage); return String.Format ("дані: image / gif; base64, {0}", base64); }
Родріго Лонго

40

Це працювало для мене

<img src="data:image;base64,@System.Convert.ToBase64String(Model.CategoryPicture.Content)" width="80" height="80"/>     

1
цей працював і для мене, ласкаво скажіть Як відобразити зображення масиву байтів у моделі, коли її нуль?
Chathz

Привіт 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
Що таке "файл повернення (...)"? Чи не Файл статичний клас?
Ben Sewards

3
Це повинен бути об’єкт FileContentResult ( msdn.microsoft.com/en-us/library/… )
Луї Бакай

13

Один із способів - додати це до нового класу 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)

Мені дуже подобається це найкраще - робить його чистим у моделі, а також у файлі .cshtml. ВЕЛИКО !!
Кен

10

Якщо ви можете базувати 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" />

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" })

3

Потрібно мати байт [] у вашій БД.

Мій байт [] є в моєму об'єкті Person:

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


Вам потрібно перетворити свій байт [] у рядок. Отже, у мене в контролері:

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. Коли ви це зробите, прив'яжіть базове значення свого перегляду у форматі

"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")
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.