ASP.Net MVC:如何显示模型中的字节数组图像

Posted

技术标签:

【中文标题】ASP.Net MVC:如何显示模型中的字节数组图像【英文标题】:ASP.Net MVC: How to display a byte array image from model 【发布时间】:2013-07-30 22:10:29 【问题描述】:

我有一个模型,其中包含我想在页面上显示的字节数组图像文件。

如何在不返回数据库的情况下做到这一点?

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

【问题讨论】:

MVC 如何在模型为空时显示字节数组图像? 【参考方案1】:

这样的事情可能会奏效......

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


<img src="@imgSrc" />

正如下面的 cmets 中所述,请在使用上述知识的前提下了解虽然这可能会回答您的问题,但可能无法解决您的问题。根据您的问题,这可能是解决方案,但我不会完全排除两次访问数据库的可能性。

【讨论】:

应该注意的是,这会将图像嵌入到 html 中,并且会绕过几种标准的图像缓存技术。 @QuintinRobinson 虽然减少了请求的数量:) @dav_i 减少初始请求的数量。在优化 Web 性能时,了解请求和处理信息的服务器、中间内容平台和客户端的机制非常重要。我不想在评论中详细说明,但我想强调需要真正理解使用这种技术的含义。 这个问题的答案可能是正确的,但我认为我们试图解决的问题存在缺陷。如果手头的问题是阻止两次调用数据库以获取数据,然后再调用一次以获取图像,我认为更好的解决方案是使用可以实现缓存的排序处理程序以减少服务器上的整体负载。当您尝试找出应用程序阻塞的原因时,因为您尝试使用 Base64 编码将一个巨大的文件转储到页面响应流中,您会希望您能更多地考虑全局。 太好了,我在模型上添加了一个方法以便重新使用它:public string GetBase64() var base64 = Convert.ToBase64String(ContentImage); return String.Format("data:image/gif;base64,0", base64); 【参考方案2】:

这对我有用

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

【讨论】:

这个也对我有用,请说如何在模型为空时显示字节数组图像? 嗨 Chathz,我建议您在传递给视图之前在控制器中验证模型。如果model为null,则传递默认图片【参考方案3】:

我推荐一些类似的东西,即使图像存在于你的模型中。

我知道您正在寻求一种直接从视图中访问它的方法,许多其他人已经回答了这个问题并告诉您这种方法有什么问题,所以这只是另一种将图像加载到对你来说异步时尚,我认为是一种更好的方法。

示例模型:

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

【讨论】:

什么是“返回文件(...)”? File 不是静态类吗? 应该是 FileContentResult 对象 (msdn.microsoft.com/en-us/library/…)【参考方案4】:

一种方法是将其添加到新的 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 文件中变得干净。太棒了!【参考方案5】:

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

在你看来:

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

【讨论】:

【参考方案6】:

如果图像不是那么大,并且很有可能您会经常重复使用该图像,并且如果您没有太多图像,并且图像不是秘密(意思是如果一个用户有可能看到另一个人的图像,这没什么大不了的)...

这里有很多“如果”,所以很有可能这是个坏主意:

您可以将图像字节存储在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", newfooId = 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,如果大于 32kB)中不起作用。

【讨论】:

【参考方案7】:

您的数据库中需要有一个 byte[]。 我的 byte[] 在我的 Person 对象中:

public class Person

    public byte[] Image  get; set; 

您需要将 byte[] 转换为字符串。所以,我有我的控制器:

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:image/图像文件扩展名;base64,0, 您的图像字符串"

我希望它能帮助别人!

【讨论】:

【参考方案8】:

这是我在项目中使用的 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));
    

然后可以这样使用:

    @Html.Image(Model.Image, "img-cls", new  ,  )

【讨论】:

【参考方案9】:

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

"data:image/[图像文件类型扩展名];base64,[你的 base64 字符串放在这里]"

以上分配给img标签的src属性。

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

【讨论】:

您提出了一个问题,并陈述了一个用例场景建议 not ,但没有针对您的用例场景的解决方案。那会让你的答案更好/有用,也更有用。【参考方案10】:

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

有一个模型:

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

【讨论】:

以上是关于ASP.Net MVC:如何显示模型中的字节数组图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.Net MVC 中将列表对象显示到视图中?

是否可以将多个模型对象发送到 ASP.NET MVC 视图?

将模型传递给 ASP.NET Core MVC 中的视图

ASP.NET MVC

如何将数据传递给 ASP.NET MVC 中的模式视图

如何根据 asp.net mvc4 中的模型列表填充 ListBox?