如何加快从Angular/Mvc.net加载图像的速度
本文关键字:加载 图像 速度 net Mvc 何加快 Angular | 更新日期: 2023-09-27 18:31:52
我有一个 MVC.net 网站,提供基于这篇旧文章的图像:
http://blogs.msdn.com/b/miah/archive/2008/11/13/extending-mvc-returning-an-image-from-a-controller-action.aspx
我的 c# 控制器代码如下所示:
public ActionResult GetThumbnail(string code)
{
byte[] image = _dataProvider.GetThumbnailImage(code);
return this.Image(image, "image/jpeg");
}
在客户端,我有一个AngularJS控制器,它从服务器加载搜索结果集。结果集包含许多图像 URL,如下所示:
<tr ng-repeat="item in data.items | filter:filter" class="fixed-height-80">
<td>
<a href="{{ item.viewDetailUrl }}"><img ng-src="{{item.thumbnailUrl}}"/></a>
</td>
</tr>
缩略图指向我的 MVC 控制器上的 GetThumbnail 操作,并在模型工厂的服务器端构造,并返回到 Angular 准备使用。
问题是图像加载非常缓慢,即使认为每个图像只有大约 3kb。在 javascript 中完成异步搜索返回后,图像一次显示一个,大约每秒一个,直到它们全部加载。
我在 .net 控制器上的 C# 中放置了一个秒表,从服务器端的 dataProvider 加载图像数据大约需要 0.9 毫秒 但即使只有十张图像要提供,在页面中加载所有图像之前也需要大约六秒钟。JS几乎立即渲染链接,只是图像很慢。
在这种情况下,如何加快图像加载速度?
更新
如果我将图像移动到~/images/image.jpg并使用Url.Content将URL直接指向文件夹,则似乎没有相同的问题。 因此,问题似乎出在控制器提供图像的方式上 - 有时如果可能需要 10 毫秒<,有时可能需要 2000 毫秒以上的时间, 但目前还不清楚为什么。
有几个选项可用:
- 通过在响应标头中添加缓存控制 HTTP 来缓存浏览器/客户端中的图像。
- 在服务器端(内存中)缓存图像,而不是对文件系统执行 I/O 操作(IIS 将缓存常用图像并从内存中提供它们)。
- 例如,使用 GZIP 压缩 HTTP 响应的资源(您应该在 Web 服务器中执行此操作)。
- 减小服务器中的图像大小/质量(可能在上传图像时)。
- 使用CSS图像精灵技术:图像精灵是放入单个图像中的图像集合,从而减少浏览器需要加载的图像数量。
- 使用专用 CDN 更快地提供图像,从而减少服务器上的加载时间。
您应该决定在您的情况下什么是最佳选择。
更新:
另外 2 个选项:
-
使用
ng-repeat
,在结果的每次迭代中,您都可以有效地访问服务器而不是访问浏览器缓存 - 可能有数百条记录。最好使用cache-control
HTTP 响应标头(HTTP 缓存标头初学者指南)发送图像,以防止一次又一次地访问服务器以获取图像并减少重复往返。 -
将图像预加载到浏览器缓存中:http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
考虑在将图像加载到服务器上后调整图像大小的选项,并将缩略图图像存储在服务器或 CDN 以及原始版本上。这将减少服务器负载,并使图像加载速度与每次请求图像时获取图像一样快,而无需进行任何处理。
使用适当的 CDN 或直接从虚拟目录提供它。你目前的实现是IIS作为Web服务器是好的和快速的,.Net框架是好的服务器端技术。
正确配置的IIS将帮助您节省带宽和文件系统I/O,如果您需要调整大小功能,请查看图像调整器
事实证明,是 MVC SessionState 导致了这个问题 - 尽管在 thgis 阶段并不完全清楚为什么。
仅为图像添加新控制器并按如下方式对其进行装饰将禁用默认会话状态行为,并防止图像卡住"等待"多年。
[SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)]
public class ImageController : Controller
{
public ActionResult GetThumbnail(string code)
{
byte[] image = _dataProvider.GetThumbnailImage(code);
return this.Image(image, "image/jpeg");
}
}