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

C# Net MVC:如何显示模型中的字节数组图像,c#,asp.net-mvc,razor,C#,Asp.net Mvc,Razor,我有一个带有字节数组图像文件的模型,我想在页面上显示它 我怎样才能在不返回数据库的情况下做到这一点 我看到的所有解决方案都使用ActionResult返回数据库检索图像,但我已经在模型上有了图像…类似的方法可能会奏效 @{ var base64 = Convert.ToBase64String(Model.ByteArray); var imgSrc = String.Format("data:image/gif;base64,{0}", base64); } <img

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

我怎样才能在不返回数据库的情况下做到这一点


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

类似的方法可能会奏效

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

<img src="@imgSrc" />
@{
var base64=Convert.tobase64字符串(Model.ByteArray);
var imgSrc=String.Format(“数据:image/gif;base64,{0}”,base64);
}

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

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

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

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

上述内容分配给
img
标记的
src
属性


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

如果图像没有那么大,如果你很有可能经常使用图像,如果图像数量不多,如果图像不是秘密的(这意味着如果一个用户可能看到另一个人的图像,这没什么大不了的)

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

您可以将图像字节短时间存储在
缓存中
,并制作一个指向操作方法的图像标记,该操作方法反过来从缓存中读取图像并吐出图像。这将允许浏览器适当地缓存图像

// 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");
}
//在原始控制器操作中
HttpContext.Cache.Add(“image-”+model.Id,model.ImageBytes,null,
Cache.NoAbsoluteExpiration,TimeSpan.FromMinutes(1),
CacheItemPriority.Normal,null);
//在你看来:
//在控制器中:
[OutputCache(VaryByParam=“fooId”,持续时间=60)]
公共操作结果GetImage(int fooId){
//确保您在适当的时候检查空值,从DB重新拉入,等等。
返回文件((字节[])HttpContext.Cache[“image-”+fooId],“image/gif”);
}
这对在旧浏览器中工作有额外的好处(或者说是一个拐杖?),在旧浏览器中,内联图像在IE7(或者IE8,如果大于32kB)中不起作用。

这对我来说很有效

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

我建议您采用这些方法,即使图像位于您的模型内部

我知道您要求的是一种直接的方式来从视图访问它,许多其他人已经回答了这一问题,并告诉您这种方式有什么问题,所以这只是另一种方式,可以异步加载映像,我认为这是一种更好的方式

示例模型:

[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");
}
控制器中的示例方法:

[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");
}
公共异步任务呈现(int-id)
{
Item Item=wait db.Items.FindAsync(id);
字节[]photoBack=item.InternalImage;
返回文件(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>
@model YourNameSpace.Models.Item
@{
ViewBag.Title=“详细信息”;
}
细节
项目

@DisplayNameFor(model=>model.Name) @DisplayFor(model=>model.Name)
一种方法是将其添加到新的c#类或HTMLEXTANSE类中

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

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

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

使用模型:

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

数据库中需要有一个字节[]。

我的字节[]位于我的Person对象中:

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

您需要将字节[]转换为字符串。因此,我的控制器中有:

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

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


我希望它能帮助别人

需要注意的是,这将把图像嵌入HTML中,并将绕过几种标准的图像缓存技术。@QuintinRobinson虽然减少了请求的数量
:)
@dav\u我减少了初始请求的数量。在优化web性能时,了解服务器、中间内容平台以及请求和处理信息的客户端的机制非常重要。我不想在评论中说得太详细,但我想强调的是,需要真正理解使用这种技术的含义。这个问题的答案可能是正确的,但我认为我们试图解决的问题有一个缺陷。如果当前的问题是阻止对数据库进行两次调用以获取数据,然后再进行第二次调用以获取图像,那么我认为更好的解决方案是使用能够实现缓存的处理程序来减少服务器上的总体负载。当您试图找出应用程序阻塞的原因,因为您试图使用Base64编码将一个巨大的文件转储到页面响应流时,您会希望您考虑了更大的问题。太好了,我在模型上添加了一个方法以重复使用:公共字符串GetBase6