【问题标题】:Streaming byte[] to Image in ASP.NET C#在 ASP.NET C# 中将字节 [] 流式传输到图像
【发布时间】:2010-11-23 17:00:55
【问题描述】:

我在我的 SQL Server 数据库中存储了一个图像,其中存储了我一次检索所有的用户数据。

现在我将字节[] 直接放在我想要显示的页面上。如何将它放在我的 WebControls.Image 中?我不想调用 HttpHandler 并再次调用数据库。

这显然只是将它输出到整个页面。

            Context.Response.BinaryWrite(user.Picture.ToArray());

【问题讨论】:

  • 图片数据不能存成文件吗?
  • 这是第一条路线,但将图像存储在数据库中是首选解决方案。 (在我头顶)所以我必须充分利用这种情况。
  • 感谢大家的帮助。快速而有见地的答案。
  • 嵌入 base64 图像是最后的手段。即使有额外的数据库流量,您最好使用单独的请求,以便页面响应更快。有a library that makes it quite easy。 SqlReader 类用作 VirtualPathProvider,它为您提供比 HttpHandler 更好的性能。您可以将它与 DiskCache 插件结合使用,以获得极佳的性能。

标签: c# asp.net sql-server image


【解决方案1】:

创建单独的页面,您将在其中创建图像,例如:image.aspx 并在其他页面上使用它

<img src="image.aspx?id=number" >

数字是图片在数据库中的id

【讨论】:

  • 不要使用 ASPX 输出图像,使用 ashx。
  • @Anthony:OP 说他们不想使用ashx,尽管我同意这是正确的做法。 (无论如何,创建aspx 并不比创建ashx 容易!)
  • @Anthony:我不知道区别。这只是扩展不是吗?可以是偶数.jpg,带路由。
  • @x2:MS 将 ASPX 文件描述为 ASP.NET Form 是有原因的。它伴随着与完整表单生命周期相关的相当大的开销(初始化控件、加载它们、处理回发、预渲染、渲染、卸载、处理等等)。如果您要做的只是调整响应对象的属性并在输出中转储一大块数据,那么您不需要这些。在这种情况下,.ashx 是更简单、更清洁的解决方案。
  • @Luke:OP 想要避免处理程序的原因是避免不得不再次从数据库中读取图片,我不认为它是对处理程序本身的厌恶,只是一个避免不必要地重复重要操作。
【解决方案2】:

将字节数组包装在 MemoryStream 对象中并将其放置在 ASP.NETs 缓存中。

MemoryStream ms = new MemoryStream(user.Picture.ToArray());
Guid imageGuid = new Guid();
HttpRuntime.Cache.Add(imageGuid.ToString(), ms, null,
    DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);

然后使用处理程序 (.ashx) 将其从缓存中取出并发送给客户端。

string imageGuid = context.Request.QueryString[image];
MemoryStream ms = (MemoryStream)HttpRuntime.Cache[imageGuid];
// configure context.Response with appropriate content type and cache settings

// ** Edit **
// It seems I need to be more explicit with regard to the above comment:-
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetLastModified(DateTime.UtcNow);
context.Response.Cache.SetExpires(DateTime.UtcNow.AddHours(2);
context.Response.Cache.SetMaxAge(TimeSpan.FromHours(2));
context.Response.Cache.SetValidUntilExpires(true);

ms.WriteTo(context.Response.OutputStream);

现在您可以从缓存中删除 MemoryStream。

HttpRuntime.Cache.Remove(imageGuid);

【讨论】:

  • 这不会跨网络农场扩展(除非你有某种分布式缓存)。
  • 永远不要这样做。您牺牲了 HTTP 的所有优点(If-Modified-Since、缓存等)和可伸缩性,但绝对没有任何好处。
  • @anton:你看到我代码中的注释行了吗?你认为我的意思是什么?
  • @Luke:相反,充分利用网络农场正是使用缓存的好处。在 WLB 环境中,会话可以并且通常与场中的服务器相关联。拥有 Web Farm 的全部意义在于承担数据库层的压力,而缓存是该解决方案中非常重要的一部分。
  • @Anthony:您的示例代码中使用的内置 ASP.NET 缓存是非分布式的:每个网络服务器都有自己的缓存。如果您的图像请求到达不同的服务器,则不会在其缓存中找到图像数据。 (如果您的网络农场使用粘性会话,这显然不适用,但这有其自身的可扩展性问题。)
【解决方案3】:

您需要一个IHttpHander,它将图像字节和正确的Content-Type 写入响应流。请参阅this、this 和 this。

【讨论】:

  • 您错过了问题中的重点。假设您在执行的 ASPX 页面中有一个从数据库获取的图像数据字节数组,您将如何在输出中获得&lt;img 以显示该图像而无需重新查询数据库??
  • @Anthony:关键是他不需要从页面本身的数据库中提取图像数据。他不需要重新查询数据库 - 他需要在适当的地点/时间(即在单独的ashx 处理程序中)查询一次。
  • @Luke:可能是这样,但我们不知道是吗?我们从这个问题中得到的只是由于某种原因他有一个已经加载了图片对象的对象。也许可以更好地避免这种情况,但将图片放在文件系统中。我更愿意回答手头的问题,特别是因为其他一些 SO 用户可能会在某些时候发现他们出于不可避免的原因处于这种情况。
  • 这也是我在 Google 上找到的唯一解决方案,但对我没有用,因为我已经从数据库中获取了一次数据,不想再浪费一个电话。
【解决方案4】:

我很确定您不能在页面本身中执行此操作。

如果您不想创建 HTTP 处理程序来输出图像,那么您的替代方法是创建一个单独的 aspx 页面。将img 标记的src 设置为指向该页面,在查询字符串中传递某种ID,以便可以从数据库中提取图像数据。

话虽如此,设置aspx 页面来执行此操作并不比设置ashx 更快或更容易。我建议以正确的方式执行此操作并创建一个 HTTP 处理程序。

【讨论】:

  • 我已经有了数据库中的数据。我想保存另一个电话。
【解决方案5】:

如果是小图像,您可以将其作为 base64 编码数据输出到图像标签中。 See here for a similar situation。

但在 99.9% 的情况下,您会创建一个返回图像的 HttpHandler。我认为这是最简单、最快的方法。

【讨论】:

  • 这正是我想要的。该图像是一个 180 x 160 像素的小 gif/jpeg。结果是这样的: byte[] picByteArray = user.Picture.ToArray();字符串 myPicString = Convert.ToBase64String(picByteArray); myPicture.Attributes["src"] = "data:image/gif;base64," + myPicString;
  • @Markoo:base64 编码时最终有多少字节?通过将图像数据直接放在动态生成的 HTML 中,您需要客户端每次都获取它,除非您使整个 html 响应可缓存,否则它是不可缓存的。
  • 我的图像最终大约为 8 KB,这在我的简单用户数据视图中是完全可以接受的。这是我公司的“内部”管理站点。虽然实际组件将在外部使用。这些外部组件和站点被我们的管理员大量缓存。所以我在实施这个解决方案时没有后顾之忧。这些配置文件非常有限。只有大约 20 或 30 名内部记者。因此,为这些设置单独的图像表似乎有点过头了。再次感谢您的洞察力。
  • 您应该小心,并非所有浏览器都可以在内联存储时读取那么多数据。请务必在您支持的所有浏览器中正确测试页面。
  • 感谢您的提示。到目前为止,我已经在 IE、FF、Chrome 中进行了测试,即使图像高达 400 KB,它也能正常工作
猜你喜欢
  • 2013-01-18
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
相关资源
最近更新 更多