ASP.Net MVC: Modelden bir bayt dizisi görüntüsü nasıl görüntülenir?


116

Sayfada göstermek istediğim bayt dizisi görüntü dosyasına sahip bir modelim var.

Veritabanına geri dönmeden bunu nasıl yapabilirim?

Gördüğüm tüm çözümler ActionResult, görüntüyü almak için veritabanına geri dönmek için bir kullanıyor , ancak görüntü zaten modelde var ...


11
Lütfen "ASP.NET MVC" ye yalnızca "MVC" olarak başvurmayı bırakın. Biri bir çerçeve iken diğeri dilden bağımsız bir tasarım modelidir. IE'yi
aramak

MVC Modelden boş olduğunda bir bayt dizisi görüntüsü nasıl görüntülenir?
Chathz

Yanıtlar:


214

Bunun gibi bir şey işe yarayabilir ...

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

<img src="@imgSrc" />

Aşağıdaki yorumlarda belirtildiği gibi, lütfen sorunuzu yanıtlayabileceği halde sorununuzu çözmeyebileceğini bilerek yukarıdakileri kullanın . Sorununuza bağlı olarak çözüm bu olabilir, ancak veritabanına iki kez erişmeyi tamamen göz ardı etmem.


6
Bunun, resmi HTML'ye götürebileceği ve birkaç standart önbellekleme tekniğini atlatacağı unutulmamalıdır.
Quintin Robinson

@QuintinRobinson İstek sayısını azaltsa da:)
dav_i

8
@dav_i İlk isteklerin sayısını azaltın . Web performansını optimize ederken, bilgileri talep eden ve işleyen sunucuların, ara içerik platformlarının ve istemcilerin işleyişini anlamak inanılmaz derecede önemlidir. Bir yorumda olağanüstü ayrıntılara girmek istemiyorum, ancak böyle bir tekniği kullanmanın sonuçlarını gerçekten anlama ihtiyacını vurgulamak istiyorum.
Quintin Robinson

1
Cevap soru için doğru olabilir ama çözmeye çalıştığımız sorunun bir kusuru olduğunu düşünüyorum. Eldeki sorun, Veri almak için veritabanına yapılan iki çağrıyı ve ardından görüntüyü almak için bir saniyeyi engelliyorsa, bence sunucudaki toplam yükü azaltmak için önbelleğe alma uygulayabilen bir işleyici kullanmak çok daha iyi bir çözüm olacaktır. Base64 kodlamasını kullanarak büyük bir dosyayı sayfa yanıt akışına atmaya çalıştığınız için uygulamanızın neden boğulduğunu anlamaya çalışırken, daha büyük resim hakkında daha fazla düşünmeyi dileyeceksiniz.
Nick Bork

2
Harika, onu yeniden kullanmak için modelime bir yöntem ekledim: public string GetBase64 () {var base64 = Convert.ToBase64String (ContentImage); dönüş String.Format ("data: image / gif; base64, {0}", base64); }
Rodrigo Longo

40

Bu benim için çalıştı

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

1
bu benim için de çalıştı, lütfen boş olduğunda modelden bir bayt dizisi görüntüsü nasıl görüntülenir?
Chathz

Merhaba Chathz, görünüme geçmeden önce denetleyicideki modeli doğrulamanızı öneririm. Model
boşsa

26

Görüntü modelinizin içinde olsa bile, bu satırlar boyunca bir şeyler öneririm.

Ona doğrudan görünümden erişmek için doğrudan bir yol istediğinizi fark ettim ve diğerleri bunu yanıtladı ve bu yaklaşımın neyin yanlış olduğunu size anlattı, bu yüzden bu, görüntüyü sizin için eşzamansız bir şekilde yükleyecek başka bir yoldur. daha iyi bir yaklaşım olduğunu düşünüyorum.

Örnek Model:

[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.
}

Kontrolörde Örnek Yöntem:

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

    byte[] photoBack = item.InternalImage;

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

Görünüm

@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
"Dönüş Dosyası (...)" nedir? File statik bir sınıf değil mi?
Ben Sewards

3
Bir FileContentResult nesnesi olmalıdır ( msdn.microsoft.com/en-us/library/… )
Louie Bacaj

14

Bunun bir yolu, bunu yeni bir c # sınıfına veya HtmlExtensions sınıfına eklemektir

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 + "' />");
    }
}

o zaman bunu herhangi bir görünümde yapabilirsiniz

@Html.Image(Model.ImgBytes)

Bunu en çok seviyorum - onu Model'de ve ayrıca .cshtml dosyasında temizliyor. HARİKA!!
Ken

10

Baytlarınızı 64 tabanına kodlayabilirseniz, sonucu görüntü kaynağınız olarak kullanmayı deneyebilirsiniz. Modelinize şöyle bir şey ekleyebilirsiniz:

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

Ve size göre:

<img ... src="@Model.ImageSource" />

5

Görsel o kadar büyük değilse ve iyi bir şans varsa, görseli sık sık yeniden kullanacaksınız ve çok fazla görseliniz yoksa ve görseller gizli değilse (yani büyük değil bir kullanıcı potansiyel olarak başka birinin resmini görebilirse) ...

Pek çok "eğer" buradaysa, bunun kötü bir fikir olma ihtimali yüksek:

Görüntü baytlarını Cachekısa bir süre için saklayabilir ve bir işlem yöntemine işaret eden bir görüntü etiketi yapabilirsiniz, bu da önbellekten okuyup görüntünüzü tükürür. Bu, tarayıcının resmi uygun şekilde önbelleğe almasına izin verecektir.

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

Bu, satır içi görüntülerin IE7'de (veya 32kB'den büyükse IE8'de) çalışmadığı eski tarayıcılarda çalışmanın ek bir yararı (veya koltuk değneği mi?) Vardır.


3

Bu, bir projede kullandığım Manoj'un cevabının değiştirilmiş bir versiyonu. Sadece bir sınıf, html nitelikleri almak ve TagBuilder'ı kullanmak için güncellendi.

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

Hangisi daha sonra aşağıdaki gibi kullanılabilir:

    @Html.Image(Model.Image, "img-cls", new { width="200", height="200" })

3

DB'nizde bir bayt [] olması gerekir.

Baytım [], Kişi nesnemde:

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


Bir String'deki [] baytınızı dönüştürmeniz gerekir. Yani, denetleyicimde:

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


Daha sonra, .cshtml dosyamda, Modelim bir ViewModel. İçinde sahip olduğum şey bu:

 public String Image { get; set; }


Bunu .cshtml dosyamda şu şekilde kullanıyorum:

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

"veri: resim / resim dosya uzantısı ; base64, {0}, resim Dizeniz "

Birine yardım etmesini diliyorum!


1

Görüntüyü sunmak istiyorsanız, yardımcı sınıf olarak veya modelin kendisine bir yöntem ekleyin ve yöntemin bayt dizisi görüntüsünü PNG veya JPG gibi bir görüntü biçimine dönüştürmesine ve ardından Base64 dizesine dönüştürmesine izin verin. Bunu aldıktan sonra, görünümünüzdeki base64 değerini formatta bağlayın

"data: image / [image file type extension] ; base64, [base64 dizeniz buraya gelecek] "

Yukarıdakiler, imgetiketin srcözniteliğine atanır .

Bununla ilgili sahip olduğum tek sorun, base64 dizesinin çok uzun olması. Bu yüzden, bir görünümde gösterilen birden fazla model için bunu tavsiye etmem.


Bir sorunu gündeme getirirsiniz ve önermeyen bir kullanım senaryosu belirtirsiniz, ancak kullanım senaryolarınız için bir çözüm sunmazsınız. Bu, cevabınızı daha güzel / yararlı ve daha bilgilendirici hale getirirdi.
Ken

0

Aşağıdaki soruya dayalı bir yardımcı yöntem oluşturdum ve bu yardımcının olabildiğince çok yardımcı olabileceğinden oldukça memnunum.

Bir modelle:

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

Yardımcı:

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

Görünüm bir: ICollection nesnesi alıyor, bu nedenle onu bir foreach ifadesinde görünümde kullanmanız gerekir:

 @foreach (var item in Model)
  @Html.GetBytes(itemP1 => item.Pic1, item.Graphics, "Idtag")
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.