ASP.Net MVC: Cara menampilkan gambar array byte dari model

115

Saya memiliki model dengan file gambar array byte yang ingin saya tampilkan di halaman.

Bagaimana saya bisa melakukannya tanpa kembali ke Database?

Semua solusi yang saya lihat menggunakan ActionResultuntuk kembali ke database untuk mengambil gambar, tetapi saya sudah memiliki gambar pada model ...

DK ALT
sumber
11
Tolong, berhenti merujuk ke "ASP.NET MVC" hanya sebagai "MVC". Salah satunya adalah kerangka kerja, sementara yang lainnya adalah pola desain bahasa-independen. Ini seperti memanggil IE - "internet"
tereško
MVC Bagaimana menampilkan gambar array byte dari model ketika nol?
Chathz

Jawaban:

214

Sesuatu seperti ini mungkin berhasil ...

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

<img src="@imgSrc" />

Seperti yang disebutkan dalam komentar di bawah, harap gunakan yang di atas dipersenjatai dengan pengetahuan bahwa meskipun ini dapat menjawab pertanyaan Anda, itu mungkin tidak menyelesaikan masalah Anda . Bergantung pada masalah Anda, ini mungkin solusinya tetapi saya tidak akan sepenuhnya mengesampingkan mengakses database dua kali.

dav_i
sumber
6
Perlu dicatat bahwa ini akan menyematkan gambar dalam HTML dan akan menghindari beberapa teknik cache gambar standar.
Quintin Robinson
@QuintinRobinson Meskipun mengurangi jumlah permintaan:)
davi
8
@davi Kurangi jumlah permintaan awal . Saat mengoptimalkan kinerja web, sangat penting untuk memahami mekanisme server, platform konten perantara, dan klien yang meminta dan memproses informasi. Saya tidak ingin membahas detail yang luar biasa dalam sebuah komentar, tetapi saya ingin menekankan perlunya benar-benar memahami implikasi penggunaan teknik semacam itu.
Quintin Robinson
1
Jawabannya mungkin benar untuk pertanyaannya tetapi saya pikir masalah yang kami coba selesaikan memiliki kekurangan. Jika masalah yang dihadapi adalah mencegah dua panggilan ke database untuk mendapatkan Data dan kemudian yang kedua untuk mendapatkan gambar, saya pikir solusi yang jauh lebih baik adalah dengan menggunakan semacam penangan yang dapat mengimplementasikan caching untuk mengurangi beban keseluruhan di server. Saat Anda mencoba mencari tahu mengapa aplikasi Anda tersedak karena Anda mencoba membuang file besar menggunakan pengkodean Base64 ke aliran respons halaman, Anda akan berharap telah memikirkan lebih banyak tentang gambaran yang lebih besar.
Nick Bork
2
Bagus, saya menambahkan metode pada model saya untuk menggunakannya kembali: string publik GetBase64 () {var base64 = Convert.ToBase64String (ContentImage); return String.Format ("data: image / gif; base64, {0}", base64); }
Rodrigo Longo
40

Ini berhasil untuk saya

<img src="data:image;base64,@System.Convert.ToBase64String(Model.CategoryPicture.Content)" width="80" height="80"/>     
NoloMokgosi
sumber
1
yang satu ini bekerja untuk saya juga, mohon katakan Bagaimana cara menampilkan gambar array byte dari model ketika nol?
Chathz
Hai Chathz, saya sarankan Anda memvalidasi model di pengontrol sebelum meneruskan ke tampilan. Jika model adalah null, berikan gambar default
NoloMokgosi
26

Saya merekomendasikan sesuatu di sepanjang garis ini, bahkan jika gambar berada di dalam model Anda.

Saya menyadari Anda meminta cara langsung untuk mengaksesnya langsung dari tampilan dan banyak orang lain telah menjawabnya dan memberi tahu Anda apa yang salah dengan pendekatan itu jadi ini hanyalah cara lain yang akan memuat gambar secara asinkron untuk Anda dan saya pikir adalah pendekatan yang lebih baik.

Model Sampel:

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

Metode Sampel di Pengontrol:

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

    byte[] photoBack = item.InternalImage;

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

Melihat

@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>
Louie Bacaj
sumber
2
Apa itu "File Pengembalian (...)"? Bukankah Mengajukan kelas statis?
Ben Sewards
3
Ini harus menjadi objek FileContentResult ( msdn.microsoft.com/en-us/library/… )
Louie Bacaj
13

Salah satu caranya adalah dengan menambahkan ini ke kelas c # baru atau kelas 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 + "' />");
    }
}

lalu Anda dapat melakukan ini dalam tampilan apa pun

@Html.Image(Model.ImgBytes)
Moji
sumber
Saya sangat suka ini yang terbaik - membuatnya bersih di Model dan juga di file .cshtml. BAGUS!!
Ken
10

Jika Anda dapat menyandikan basis 64 byte Anda, Anda dapat mencoba menggunakan hasilnya sebagai sumber gambar Anda. Dalam model Anda, Anda dapat menambahkan sesuatu seperti:

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

Dan menurut pandangan Anda:

<img ... src="@Model.ImageSource" />
Cᴏʀʏ
sumber
5

Jika gambarnya tidak terlalu besar, dan jika ada kemungkinan besar Anda akan sering menggunakan kembali gambar itu, dan jika Anda tidak memiliki terlalu banyak gambar, dan jika gambarnya tidak rahasia (artinya tidak besar. kesepakatan jika satu pengguna berpotensi melihat gambar orang lain) ...

Banyak "jika" ada di sini, jadi kemungkinan besar ini adalah ide yang buruk:

Anda dapat menyimpan byte gambar Cacheuntuk waktu yang singkat, dan membuat tag gambar mengarah ke metode tindakan, yang pada gilirannya membaca dari cache dan mengeluarkan gambar Anda. Ini akan memungkinkan browser untuk menyimpan gambar dengan benar.

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

Ini memiliki manfaat tambahan (atau apakah itu kruk?) Untuk bekerja di browser lama, di mana gambar sebaris tidak berfungsi di IE7 (atau IE8 jika lebih besar dari 32kB).

Joe Enos
sumber
3

Ini adalah versi modifikasi dari jawaban Manoj yang saya gunakan dalam sebuah proyek. Baru saja diperbarui untuk mengambil kelas, atribut html, dan menggunakan 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));
    }

Yang dapat digunakan kemudian sebagai berikut:

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

Anda harus memiliki byte [] di DB Anda.

Byte [] saya ada di objek Person:

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


Anda perlu mengonversi byte Anda [] menjadi String. Jadi, saya ada di pengontrol saya:

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


Selanjutnya, dalam file .cshtml saya, Model saya adalah ViewModel. Inilah yang saya miliki:

 public String Image { get; set; }


Saya menggunakannya seperti ini di file .cshtml saya:

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

"data: ekstensi file gambar / gambar ; base64, {0}, String gambar Anda "

Saya berharap ini akan membantu seseorang!

Thorpe
sumber
1

Jika Anda ingin menampilkan gambar, tambahkan metode sebagai kelas pembantu atau model itu sendiri dan izinkan metode untuk mengonversi gambar array byte ke format gambar seperti PNG atau JPG, lalu ubah ke string Base64. Setelah Anda memilikinya, ikat nilai base64 pada tampilan Anda dalam format

"data: image / [ekstensi jenis file gambar] ; base64, [string base64 Anda ditempatkan di sini] "

Di atas ditetapkan ke atribut imgtag src.

Satu-satunya masalah yang saya miliki dengan ini adalah string base64 yang terlalu panjang. Jadi, saya tidak akan merekomendasikannya untuk beberapa model yang ditampilkan dalam satu tampilan.

mitch
sumber
Anda mengemukakan masalah, dan menyatakan skenario kasus penggunaan yang tidak merekomendasikan, tetapi tidak ada solusi untuk skenario kasus penggunaan Anda. Itu akan membuat jawaban Anda jauh lebih bagus / berguna dan lebih informatif.
Ken
0

Saya telah membuat metode helper berdasarkan asnwer di bawah ini dan saya cukup senang bahwa helper ini dapat membantu sebanyak mungkin.

Dengan model:

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

Pembantu adalah:

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

Tampilan menerima: objek ICollection jadi Anda perlu menggunakannya dalam tampilan di pernyataan foreach:

 @foreach (var item in Model)
  @Html.GetBytes(itemP1 => item.Pic1, item.Graphics, "Idtag")
}
Jose Ortega
sumber