【问题标题】:Displaying database image (bytes[]) in Razor/MVC3?在 Razor/MVC3 中显示数据库图像(字节 [])?
【发布时间】:2012-01-18 11:26:40
【问题描述】:

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

由于字节数组相对较小,我想我会尝试内联显示字节数组。不过看了之后可能有一些浏览器相关的问题,我放弃了这个。

创建一个控制器方法似乎是可行的方法,(这两个方法都找到了here),但是我已经准备好字节数组,可以在我的视图中使用,并且不需要进行另一个数据库调用来获得它在身份证上。

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

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

@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[]...)) 但这在这种情况下不起作用。

-- 更新--

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

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

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

-- 更新--

这一直困扰着我...所以我尝试了以下方法,我认为这可能有效,因为这是我们在 Action 中所做的...

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

...不起作用。

【问题讨论】:

  • 我还没有看到从模型/视图模型中获取并显示的图像示例(除了我使用 TempData 的答案)。你会认为这是一个常见的要求,但要么它很简单,没有人问,要么很困难,没有人打扰。您尝试过 TempData 解决方案吗?
  • 我知道这不是我的问题,但是... 什么是反对票?这是一个很好的问题 - 太好了,以至于没有人有一个不涉及额外的数据库旅行或浏览器愚蠢的解决方案。反对者至少应该发表评论。
  • 是的,说真的 - 因为我对低效的解决方案不满意? :) 不得不再次往返数据库似乎效率非常低,因为我已经准备好所有数据(图像再见和所有)都可以继续查看。我正在尝试提出一些不同的途径,并且使用 WebImage 帮助器是我得到的最接近的方法 - 它实际上显示了图像,但它是页面上唯一的内容。
  • 我正在经历这个确切的痛苦。我允许用户一次上传最多 10 张图片,然后在保存后将它们显示在详细信息视图中,这让我的问题变得更糟。

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


【解决方案1】:

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

【讨论】:

  • 是的,转换为 base64 字符串非常适合缩略图等较小的图像,它消除了让视图处理原始二进制数据的问题。我也有同样的问题,但是对于存储在 SQL 中的较大图像。
【解决方案2】:

以下将起作用:

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

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

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

【讨论】:

  • 我还没有机会尝试,但它看起来会起作用 - 比额外往返数据库更有效。
【解决方案3】:

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

获取字节(是的,从头再来):

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

【讨论】:

  • 您所要求的不是大多数网络浏览器的工作方式。图像标签使用自己的 URI 链接到外部文档。这就是为什么你需要这样做。如果您对此感到担心,请将图像保存到文件中,并让数据库保留该文件的 URL。然后你打一次。或者,较新的浏览器在某些情况下支持数据 URI。请参阅en.wikipedia.org/wiki/Data_URI_scheme 了解更多信息。
  • 我知道这是一个较老的问题,但只要投入 2 美分,如果您在 Web 服务器上使用缓存,则不需要再次访问数据库。缓存最后一个 db 调用几分钟,以便当浏览器第 n 次调用获取图像时,从缓存中获取数据。此外,我想对使用 FileContentResult 的漂亮示例表示感谢。这在我自己的应用程序中帮助了我。所以...谢谢!
  • 这对我们有用 @: 只要 Razor 托管在 asp MVC 应用程序中(如果您在外部托管它,请说赢表不开心)
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    您可以在 Controller 操作中执行 Response.Write(您的字节数组) 并将 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" />
    

    因此,换句话说,不是直接在视图中使用字节,而是调用一个控制器操作,它根据行的 Id(或产品,如果那是行)

    它可能不能完全回答您的问题,但它会起作用。

    【讨论】:

    • 已经有数据显示在页面上的其他图像、文本等。缩略图是数据表行的一部分,其中显示了数据表的其余部分。我不想将整个响应内容类型设置为 image/jpeg。
    • 澄清一下,您的建议是,对于每个图像,调用 GetImage() 将根据 ID 返回图像,对吗?
    • @ElHaix:是的,就是这样。如果您不喜欢为字节敲击数据库两次,您可以从初始查询中省略字节,并仅选择 GetImage 操作中的字节..
    • 为什么这被否决了?评论以及它赞赏的反对票!
    • 可能是同一个反对我最初的问题的仇恨者。我赞成中和。
    【解决方案6】:

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

    更多关于这个问题的信息可以在这里找到More problem details

    最后,为了避免破解我认为可能是 IE9 中的错误,我选择了“两个”读取,但应该没有必要。

    【讨论】:

      【解决方案7】:

      我不认为在您的视图中有一个字节数组会对您有所帮助。您需要使用控制器操作作为 linked answer 中所述的 img src。

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

      【讨论】:

      • 对,但正如我所提到的,我已经有了字节数组。必须回去拿它似乎效率低下,因为我已经有了它。
      • 即使已经有了,也不能用字节数组在html中显示图片。浏览器需要对每张图片进行单独的请求。
      猜你喜欢
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-03
      • 2011-10-19
      • 2011-11-25
      • 2019-08-14
      • 1970-01-01
      相关资源
      最近更新 更多