MVC How to display a byte array image from model

2019-01-01 13:04发布

I've a model with a byte array image file that I want to show on the page.

How can I do that without going back to the Database?

All the solutions that I see use an ActionResult to go back to the database to retrieve the image, but I already have the image on the model...

10条回答
只靠听说
2楼-- · 2019-01-01 13:29

You need to have a byte[] in your DB.

My byte[] is in my Person object:

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


You need to convert your byte[] in a String. So, I have in my controller :

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


Next, in my .cshtml file, my Model is a ViewModel. This is what I have in :

 public String Image { get; set; }


I use it like this in my .cshtml file:

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

"data:image/image file extension;base64,{0}, your image String"

I wish it will help someone !

查看更多
路过你的时光
3楼-- · 2019-01-01 13:29

If you want to present the image, add a method as a helper class or to the model itself and allow the method to convert the byte array image to a image format like PNG or JPG then convert to Base64 string. Once you have that, bind the base64 value on your view in the format

"data:image/[image file type extension];base64,[your base64 string goes here]"

The above is assigned to the img tag's src attribute.

The only issue I have with this is the base64 string being too long. So, I would not recommend it for multiple models being shown in a view.

查看更多
荒废的爱情
4楼-- · 2019-01-01 13:33

If you can base-64 encode your bytes, you could try using the result as your image source. In your model you might add something like:

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

And in your view:

<img ... src="@Model.ImageSource" />
查看更多
倾城一夜雪
5楼-- · 2019-01-01 13:34

If the image isn't that big, and if there's a good chance you'll be re-using the image often, and if you don't have too many of them, and if the images are not secret (meaning it's no big deal if one user could potentially see another person's image)...

Lots of "if"s here, so there's a good chance this is a bad idea:

You can store the image bytes in Cache for a short time, and make an image tag pointed toward an action method, which in turn reads from the cache and spits out your image. This will allow the browser to cache the image appropriately.

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

This has the added benefit (or is it a crutch?) of working in older browsers, where the inline images don't work in IE7 (or IE8 if larger than 32kB).

查看更多
余欢
6楼-- · 2019-01-01 13:39

I recommend something along these lines, even if the image lives inside of your model.

I realize you are asking for a direct way to access it right from the view and many others have answered that and told you what is wrong with that approach so this is just another way that will load the image in an async fashion for you and I think is a better approach.

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

Sample Method in the Controller:

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

    byte[] photoBack = item.InternalImage;

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

View

@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>
查看更多
无色无味的生活
7楼-- · 2019-01-01 13:40

One way is to add this to a new c# class or HtmlExtensions class

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

then you can do this in any view

@Html.Image(Model.ImgBytes)
查看更多
登录 后发表回答