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


115

我有一个要在页面上显示的带有字节数组图像文件的模型。

在不返回数据库的情况下该如何做?

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


11
请不要再将“ ASP.NET MVC”简称为“ MVC”。一个是框架,而另一个是与语言无关的设计模式。这就像调用IE浏览器- “网络”
tereško

MVC当null时如何显示模型中的字节数组图像?
Chathz '16

Answers:


214

这样的事情可能会起作用...

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

<img src="@imgSrc" />

如以下评论中所述,请使用上面的知识,尽管这可能会回答您的问题,但可能无法解决您的问题。根据您的问题,这可能是解决方案,但我不会完全排除两次访问数据库的可能性。


6
应当注意,这会将图像嵌入HTML中,并且会规避几种标准的图像缓存技术。
Quintin Robinson

@QuintinRobinson虽然减少了请求的数量:)
dav_i

8
@dav_i减少初始请求的数量。在优化Web性能时,了解请求和处理信息的服务器,中间内容平台和客户端的机制非常重要。我不想在评论中涉及非凡的细节,但我想强调需要真正了解使用这种技术的含义。
Quintin Robinson

1
这个问题的答案可能是正确的,但我认为我们要解决的问题有缺陷。如果当前的问题是阻止对数据库的两次调用来获取数据,然后阻止第二次获取图像,那么我认为更好的解决方案是使用可以实现缓存的排序处理程序,以减少服务器的总体负载。当您试图弄清为什么应用程序令人窒息的原因是,您试图使用Base64编码将巨大的文件转储到页面响应流时,您希望您已对更大的图景有更多的考虑。
尼克·博克

2
太好了,我在模型上添加了一个方法以重新使用它:public string GetBase64(){var base64 = Convert.ToBase64String(ContentImage); 返回String.Format(“ data:image / gif; base64,{0}”,base64); }
罗德里戈·隆戈

40

这对我有用

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

1
这个也对我有用,请说如何在模型为null时显示来自模型的字节数组图像?
Chathz '16

嗨,Chathz,我建议您在传递到视图之前在控制器中验证模型。如果模型为null,传递一个默认图片
NoloMokgosi

26

即使图像存在于模型中,我也建议遵循这些原则。

我知道您正在要求从视图直接访问它的直接方法,许多其他人都回答了这一问题,并告诉您该方法有什么问题,因此这只是另一种以异步方式为您和我加载图像的方法认为是更好的方法。

样品型号:

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

2
什么是“返回文件(...)”?File不是静态类吗?
本·塞沃斯

3
它应该是一个FileContentResult对象(msdn.microsoft.com/en-us/library/...
路易Bacaj

13

一种方法是将其添加到新的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)

我真的很喜欢这样做-在Model和.cshtml文件中使其干净。大!!
肯(Ken)

10

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

5

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

这里有很多“ if”,因此很有可能是个坏主意:

您可以在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", 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");
}

在较旧的浏览器中使用内联图像在IE7(或大于8kB的IE8)中不起作用的旧浏览器中,这具有额外的好处(或者是拐杖吗?)。


3

这是我在项目中使用的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 { width="200", height="200" })

3

您的数据库中需要有一个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)" />

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

希望它能对某人有所帮助!


1

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

“ data:image / [图像文件类型扩展名] ; base64,[您的base64字符串在此处]

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

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


您提出了一个问题,并提出了一个用例场景,建议您不要使用,但是没有用例解决方案。那将使您的答案更好/更有用,更有用。
肯(Ken)

0

我已经在下面的清单中创建了一个帮助程序方法,我很高兴该帮助程序可以提供尽可能多的帮助。

使用模型:

 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")
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.