在Razor / MVC3中显示数据库图像(bytes [])?

时间:2011-12-12 13:09:05

标签: asp.net-mvc-3 c#-4.0 bytearray razor

我从MS SQL 2008R2数据库返回一个数据集,该数据集包含一个我已经从Razor视图中获取数据的数据表。我添加了一个byte []字段,其中包含我试图在该视图上显示的图像缩略图。

由于字节数组相对较小,我想我会尝试内联显示字节数组。但是,阅读后可能会出现一些与浏览器相关的问题,我放弃了这一点。

创建一个控制器方法似乎是要走的路(两个方法都找到here),但是我已经准备好了我的视图上的字节数组,并且不需要再进行另一个db调用它基于ID。

这样做,由于显而易见的原因不起作用:

...在页面上显示其他数据....

@if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] == null)
{
    <img src="@Url.Content("~/Content/Images/NoPhoto.png")" border="0" />
}
else
{
    <img src="@Url.Action("GetImage", "SearchResults", new { imageBytes = Model.dsResults.Tables[0].Rows[i]["ImageBytes"] })" alt="Product Image" />
}

...

控制器方法:

[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetImage(byte[] imageBytes)
{
    byte[] byteArray = imageBytes;
    return new FileContentResult(byteArray, "image/jpeg");
}

...因为这本质上是试图通过http发送字节数组。

所以,我的问题是,因为我的Razor视图上已经有了字节数组,我该如何显示呢?

- 更新 -

我意识到不建议在视图中进行处理,但由于数据已经存在,所以不能这样做:

Response.Write((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]);

或者...

Stream s = new MemoryStream(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
System.Drawing.Image img = new System.Drawing.Bitmap(s);

在其他帖子中,我读过你做了一个Response.Write(byte [] ...))但这在这种情况下不起作用。

- UPADATE -

在我不断寻求效率的过程中(不必向数据库发出另一个请求),WebImage帮助器似乎是一个很好的候选者。它的一个构造函数将接受一个字节数组来初始化类,然后使用.Write(“jpeg”)方法,我可以看到图像。

<td>
    @{
        WebImage webImage = new WebImage(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
        webImage.Write("jpeg");
    }
</td>

使用WebImage.Write()的问题是,一旦使用,图像就是在页面上呈现的唯一内容。有没有办法将它直接渲染到Razor视图页面上的“控件”?

- 更新 -

这继续让我感到烦恼......所以我尝试了下面的内容,我认为这可能有用,因为这是我们从行动中做的......

if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] != DBNull.Value)
{
    var img1 = new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg");
    <text>
        <img src="@new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg")" />
    </text>
}

......不起作用。

7 个答案:

答案 0 :(得分:20)

Model.Content是一个byte []图像。

@{
    string imageBase64 = Convert.ToBase64String(Model.Content);
    string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);
}

像这样使用:

<img src="@imageSrc" alt="@Model.Name" width="100" height="100" />

答案 1 :(得分:9)

最终,我选择了两条路线。效率非常低,因为图像字节已经准备好进入视图。应该有一个Web辅助图像控件,它将直接从图像的字节数组(或图像类型)渲染图像。也许有,我错过了。

获取字节(是的,重新开始):

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult GetThumbnailImage(string itemListID)
    {
        byte[] imageBytes = null;

        client = new FeederServiceClient();
        imageBytes = client.GetItemThumbnail( itemListID );

        if (imageBytes == null)
        {
            return new FilePathResult("~/Content/Images/NoPhoto.png", "image/png");
        }
        else
        {
            return new FileContentResult(imageBytes, "image/jpeg");
        }
    }

然后显示图像:

<img src="@Url.Content("~/Thumbnails/" + @Model.dsResults.Tables[0].Rows[i]["ItemListID"] )" />

将以下路线放在Global.asax中:

routes.MapRoute(name: "Thumbnails", url: "Thumbnails/{itemListID}", defaults: new { controller = "Results", action = "GetThumbnailImage" });

答案 2 :(得分:5)

我认为View中没有字节数组会对你有帮助。您需要使用控制器操作作为img src,如linked answer中所述。

[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Image(int id)
{
    byte[] byteArray = _imageRepository.GetImage(id);
    return new FileContentResult(byteArray, "image/jpeg");
}


<img src="Image/1234" alt="Image 1234"/>

答案 3 :(得分:3)

以下内容可行:

<img src="data:image/jpg;base64,@(Convert.ToBase64String(item.PhotoImage))" alt="@item.orientation" />

在我的应用程序中,我将RAZOR页面上的模型定义为项目,而不是模型。 PhotoImage是我的字节数组(实际上是SQL中的图像字段),Orientation只是一个字符串列,用于告知有关照片的元数据。

在我找到这个答案之前,我搜索了很长时间,这对我有用。希望它有所帮助。

答案 4 :(得分:2)

您可以执行Response.Write(您的字节数组)并在Controller操作中将Response.ContentType设置为image / jpeg。这将直接显示为图像。

<强>更新

代码看起来像这样:

    [Authorize]
    [AcceptVerbs(HttpVerbs.Get)]
    public void GetImage(int id)
    {
        byte[] imageArray = GetImageBytesFromDb(id); // some method for returning the byte-array from db.
        Response.ContentType = "image/png";
        Response.Write(imageArray);       
    }

现在,您可以在视图中执行以下操作:

 <img src="@Url.Action("GetImage", "SearchResults", new { id= Model.dsResults.Tables[0].Rows[i]["Id (or whatever the id of the row is)"] })" alt="Product Image" />

因此,换句话说,不是直接在视图中使用字节,而是调用一个controller-action,它根据行(或产品的Id)从数据库行返回字节,如果这是行的实体行)

这可能不是你问题的答案,但它会奏效。

答案 5 :(得分:0)

这是避免第二次不必要的数据库访问的一种方法。 memorystream to Image但是当它在IE9中使用时它会带来它自己的问题(所有其他浏览器和IE版本似乎都可以正常工作)。

有关此问题的更多信息,请访问More problem details

最后,为了不对我认为可能是IE9中的错误进行攻击,我选择了“两个”读取,但不应该有这个需要。

答案 6 :(得分:0)

如果您不介意使用Session,可以将模型放入Session(异端!),然后将视图渲染为正常但现在您想要显示图像的位置,您可以使用Url.Action调用控制器操作传递它你想要的图像的Id。然后将模型拉回会话,在模型中找到该ID的图像,在字节数组上执行FiLeContentResult(数组,imgtype),并将中提琴图像从模型直接导入到页面中。无需再次访问真实数据库但是如果使用Session SQL State然后obv。你将比以前更糟糕地击中数据库,但如果你是InProc ......那么它是一种方法。 我不确定IE9是否仍然存在缓存方面的小问题,但您始终可以将唯一ID与您的真实ID一起传递,以确保不会发生。 这是一个破旧的解决方案,但确实有效。