MVC如何显示来自模型的字节数组图像

时间:2022-09-01 21:22:56

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

我看到的所有解决方案都使用ActionResult返回数据库检索图像,但是我已经在模型上有了图像…

10 个解决方案

#1


149  

Something like this may work...

像这样的东西可能有用……

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

<img src="@imgSrc" />

As mentioned in the comments below, please use the above armed with the knowledge that although this may answer your question it may not solve your problem. Depending on your problem this may be the solution but I wouldn't completely rule out accessing the database twice.

正如下面评论中提到的,请使用上面的知识,尽管这可能回答你的问题,但它可能不能解决你的问题。根据您的问题,这可能是解决方案,但我不完全排除两次访问数据库。

#2


25  

This worked for me

这为我工作

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

#3


18  

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>

#4


10  

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

一种方法是将它添加到一个新的c#类或htmlextense类

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)

#5


8  

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:

如果可以对字节进行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);
    }
}

And in your view:

在你的观点:

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

#6


5  

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).

这对在旧浏览器中工作有额外的好处(或者它是一个拐杖?),在旧浏览器中内联图像在IE7中不能工作(或者在大于32kB的IE8中不能工作)。

#7


1  

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

My byte[] is in my Person object:

您需要在DB中有一个字节[]。我的byte[]在我的Person对象:

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 :

接下来,在我的.cshtml文件中,我的模型是一个ViewModel。这就是我所拥有的:

 public String Image { get; set; }


I use it like this in my .cshtml file:

我在。cshtml文件中这样使用它:

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

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

“数据:图像/图像文件扩展;base64,{0},您的图像字符串”

I wish it will help someone !

我希望它能帮助某人!

#8


0  

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

如果您想要显示图像,请添加一个方法作为辅助类或模型本身,并允许该方法将字节数组图像转换为像PNG或JPG这样的图像格式,然后将其转换为Base64字符串。一旦有了它,就以这种格式绑定视图上的base64值

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

"data:image/[image file type extension];base64,[你的base64字符串到这里]"

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

上面的内容被分配给img标记的src属性。

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.

我唯一的问题是base64字符串太长了。因此,我不建议在视图中显示多个模型。

#9


0  

This is an modified version of Manoj's answer that I use on a project. Just updated to take a class, html attributes and use the TagBuilder.

这是我在一个项目中使用的Manoj的修正版本。只需更新一个类、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));
    }

Which can be used then as follows:

可采用以下方法:

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

#10


0  

I've created a helper method based in the asnwer below and I'm pretty glad that this helper can help as many as possible.

我在下面的asnwer中创建了一个帮助器方法,我很高兴这个帮助器可以帮助尽可能多的人。

With a model:

一个模型:

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

The helper is:

助手:

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

The view is receiving a: ICollection object so you need to used it in the view in a foreach statement:

视图正在接收一个:ICollection对象,因此您需要在foreach语句的视图中使用它:

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

#1


149  

Something like this may work...

像这样的东西可能有用……

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

<img src="@imgSrc" />

As mentioned in the comments below, please use the above armed with the knowledge that although this may answer your question it may not solve your problem. Depending on your problem this may be the solution but I wouldn't completely rule out accessing the database twice.

正如下面评论中提到的,请使用上面的知识,尽管这可能回答你的问题,但它可能不能解决你的问题。根据您的问题,这可能是解决方案,但我不完全排除两次访问数据库。

#2


25  

This worked for me

这为我工作

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

#3


18  

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>

#4


10  

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

一种方法是将它添加到一个新的c#类或htmlextense类

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)

#5


8  

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:

如果可以对字节进行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);
    }
}

And in your view:

在你的观点:

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

#6


5  

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).

这对在旧浏览器中工作有额外的好处(或者它是一个拐杖?),在旧浏览器中内联图像在IE7中不能工作(或者在大于32kB的IE8中不能工作)。

#7


1  

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

My byte[] is in my Person object:

您需要在DB中有一个字节[]。我的byte[]在我的Person对象:

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 :

接下来,在我的.cshtml文件中,我的模型是一个ViewModel。这就是我所拥有的:

 public String Image { get; set; }


I use it like this in my .cshtml file:

我在。cshtml文件中这样使用它:

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

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

“数据:图像/图像文件扩展;base64,{0},您的图像字符串”

I wish it will help someone !

我希望它能帮助某人!

#8


0  

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

如果您想要显示图像,请添加一个方法作为辅助类或模型本身,并允许该方法将字节数组图像转换为像PNG或JPG这样的图像格式,然后将其转换为Base64字符串。一旦有了它,就以这种格式绑定视图上的base64值

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

"data:image/[image file type extension];base64,[你的base64字符串到这里]"

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

上面的内容被分配给img标记的src属性。

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.

我唯一的问题是base64字符串太长了。因此,我不建议在视图中显示多个模型。

#9


0  

This is an modified version of Manoj's answer that I use on a project. Just updated to take a class, html attributes and use the TagBuilder.

这是我在一个项目中使用的Manoj的修正版本。只需更新一个类、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));
    }

Which can be used then as follows:

可采用以下方法:

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

#10


0  

I've created a helper method based in the asnwer below and I'm pretty glad that this helper can help as many as possible.

我在下面的asnwer中创建了一个帮助器方法,我很高兴这个帮助器可以帮助尽可能多的人。

With a model:

一个模型:

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

The helper is:

助手:

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

The view is receiving a: ICollection object so you need to used it in the view in a foreach statement:

视图正在接收一个:ICollection对象,因此您需要在foreach语句的视图中使用它:

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