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

135
我有一个带有字节数组图像文件的模型,我想在页面上显示它。如何做到在不返回数据库的情况下实现?所有我看到的解决方案都使用一个 ActionResult 返回数据库来检索图像,但我已经在模型中有了图像...

MVC如何在模型为null时显示字节数组图像? - Chathz
10个回答

257

这样的东西可能会有用...

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

<img src="@imgSrc" />

如下方评论所述,请使用上述方法,并注意虽然这可能回答了你的问题,但可能无法解决你的问题。根据你的问题,这可能是解决方案,但我不会完全排除两次访问数据库的可能性。


7
需要翻译的内容:It should be noted this will embed the image in the HTML and will circumvent several standard image caching techniques.这将嵌入图片至HTML中,并避开一些标准的图片缓存技术。 - Quintin Robinson
8
减少 初始 请求的数量。 在优化 Web 性能时,了解服务器、中间内容平台以及请求和处理信息的客户端的机制非常重要。我不想在评论中详细介绍,但我想强调有必要真正理解使用这种技术的影响。 - Quintin Robinson
2
答案可能对问题是正确的,但我认为我们试图解决的问题有一个缺陷。如果手头的问题是防止两次调用数据库来获取数据,然后再进行第二次调用以获取图像,那么更好的解决方案是使用某种处理程序来实现缓存,以减少服务器的总体负载。当您试图弄清楚为什么应用程序因为尝试使用Base64编码将巨大文件转储到页面响应流而出现故障时,您会希望自己更多地考虑整体情况。 - Nick Bork
@NickBork 已更新,含有此处所述的警示。 - dav_i
3
太好了,我在我的模型上添加了一个方法以便重复使用它: public string GetBase64() { var base64 = Convert.ToBase64String(ContentImage); return String.Format("data:image/gif;base64,{0}", base64); } - Rodrigo Longo
显示剩余4条评论

54

这对我起作用了

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

1
这个对我也起作用了,可以请问一下当模型中的字节数组图像为空时如何显示? - Chathz
3
嗨,Chathz,我建议在将模型传递到视图之前在控制器中对其进行验证。如果模型为空,则传递默认图片。 - NoloMokgosi

28

我建议采取类似的方法,即使图像是在模型内部。

我知道你想要直接从视图中访问它,而且很多人已经回答了这个问题,并告诉你那种方法的问题,所以这只是另一种方法,可以异步加载图像,并且我认为这是更好的方法。

样例模型:

[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
"return File(...)" 是什么意思?File 不是一个静态类吗? - Ben Sewards
3
应该是一个FileContentResult对象(https://msdn.microsoft.com/zh-cn/library/system.web.mvc.filecontentresult(v=vs.118).aspx)。 - Louie Bacaj

14

其中一种方法是将此内容添加到新的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文件都变得更加清晰。太棒了! - Ken

10
如果你能将字节进行Base64编码,你可以尝试使用结果作为图片来源。在你的模型中,你可以添加类似以下的内容:
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

你需要在数据库中有一个byte[]。

我的byte[]存储在Person对象中:

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

您需要将byte[]转换为字符串。因此,在我的控制器中有以下内容:
String img = Convert.ToBase64String(person.Image);

接下来,在我的.cshtml文件中,我的模型是一个视图模型。这是我在中的内容:

 public String Image { get; set; }

我在我的.cshtml文件中使用它的方式如下:
<img src="@String.Format("data:image/jpg;base64,{0}", Model.Image)" />

"数据:image/图像文件扩展名;base64,{0}, 你的图片字符串"

希望能对某人有所帮助!


5
如果图片不是很大,而且有很大的可能性会经常重复使用,而且你没有太多这样的图片,而且这些图片不是机密的(也就是说如果一个用户可能看到另一个人的图片也没什么大不了的)......
这里有很多“如果”,所以这很可能是个坏主意:
你可以在短时间内将图像字节存储在缓存中,并创建一个指向操作方法的图像标记,该方法从缓存中读取并输出你的图像。这将允许浏览器适当地缓存图像。
// 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(或大于32kB的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" })

1
如果你想展示图片,可以将一个方法添加为帮助类或模型本身的一部分,并允许该方法将字节数组图像转换为像PNG或JPG这样的图像格式,然后再转换为Base64字符串。一旦你有了这个,就可以在视图中以以下格式绑定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")
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接