加载图片库在Razor View中花费太多时间

时间:2017-03-29 12:13:05

标签: javascript c# asp.net asp.net-mvc image

我在ASP.NET MVC项目中使用名为Unite Gallery插件的图库插件,以显示存储在数据库中的图像。但是,同时加载所有图像需要很长时间(因为每张照片的大小为1MB-4MB,并且在页面加载时同时加载500张照片不是一个好主意)我认为必须有一个更好的方法即asenkron加载或部分加载。这是我的Razor和Controller代码。我查看了wweb和docs上的许多页面,但documentation页面中没有示例。你有什么主意吗?

<div id="gallery" style="display:none;">        

    @foreach (var item in Model)
    {
        if (item.FileData != null)
        {
            var base64 = Convert.ToBase64String(item.FileData);
            var imgSrc = String.Format("data:image/gif;base64,{0}", base64);

            <img alt='Image'
                    src="@imgSrc"
                    data-image="@imgSrc"
                    data-description='Image'>
        }
    }
</div>

<script type="text/javascript">

    jQuery(document).ready(function () {
    var gallery = jQuery("#gallery").unitegallery({
        gallery_theme: "default" //theme skin
    });

    gallery.on("item_change", function (num, data) {
        if((num%15) == 0)
        {
            $.ajax({
                url: '@Url.Action("List", "PhotoContest")',
                data: { isAll: isAllChecked, page: num }, //??? I pass the page parameter???
              success: function(data){
                //call is successfully completed and we got result in data

                //??? NO IDEA ???

              },
              error:function (xhr, ajaxOptions, thrownError){
                              //some errror, some show err msg to user and log the error
                              alert(xhr.responseText);
                            }
              });
        }
    });

});

</script>


public ActionResult List(string query)
{
    var model = db.Photo.Select(m => new PhotoViewModel
    {
        Id = m.Id,
        Name = m.Name,
        StatusId = m.StatusId,
        SubmitDate = m.SubmitDate,
        FileAttachments = m.FileAttachments,
        SubmitNo = m.SubmitNo
    })
    .ToArray();

    return View("List", model);
}

更新

在尝试应用@Kris的完美方法后,我遇到了如下所示的错误。在网络上没有关于此特定问题的修复或解决方案。任何的想法?

enter image description here

页面加载后的图像会重载div和gallery边框,如下所示:

enter image description here

2 个答案:

答案 0 :(得分:2)

一次加载30张图片

  

在Unite gallery中提供的Itemchange事件中加载剩余

主页

<div id="gallery" >
<input type="hidden" id="galleryPage" value="0"/>
@HTML.Action("GalleryImages") //first load 30 items as PageNo = 0
</div>

<script type="text/javascript">
var gallery;
    jQuery(document).ready(function () {
    gallery = jQuery("#gallery").unitegallery({
        gallery_theme: "default" //theme skin
    });

    gallery.on("item_change", function (num, data) {
      //when item loaded equals to 15 or 30 or multiples of 15 another 30 items get loaded
        if((num%15) == 0)
        {
            $.ajax({
                url: '@HTML.Action("GalleryImages")'+"?pageNo="+jQuery("galleryPage").val(),
                data: { isAll: isAllChecked },
              success: function(data){
               jQuery("gallery").append(data);//partial view with new images
               jQuery("galleryPage").val(gallery.getNumItems()/30); //page number total items/number of items per page
              },
              error:function (xhr, ajaxOptions, thrownError){
                              //some errror, some show err msg to user and log the error
                              alert(xhr.responseText);
                            }
              });
        }
    });

});

</script>

部分视图(_galleryImages.cshtml)

@foreach (var item in Model)
    {
        if (item.FileData != null)
        {
            var base64 = Convert.ToBase64String(item.FileData);
            var imgSrc = String.Format("data:image/gif;base64,{0}", base64);

            <img alt='Image'
                    src="@imgSrc"
                    data-image="@imgSrc"
                    data-description='Image'>
        }
    }

控制器

 //Main View
    public ActionResult List()
    {
            return View();
    }

//Partial View
public Action GalleryImages(int PageNo)
{
    int PageSize = 30;
     var model = db.Photo.Select(m => new PhotoViewModel
    {
        Id = m.Id,
        Name = m.Name,
        StatusId = m.StatusId,
        SubmitDate = m.SubmitDate,
        FileAttachments = m.FileAttachments,
        SubmitNo = m.SubmitNo
    }).Skip(PageNo*PageSize).Take(PageSize).ToArray();

    return PartialView("_galleryImages", model);
}

答案 1 :(得分:1)

我认为这里只有一个问题。首先,无论你做什么,一次加载100张图像都会很慢。对于这一点,@ Kris可能有正确的想法。我不熟悉这个特定的库,但如果它提供了一种逐步加载少量图像的方法,那么你一定要使用它。

第二个问题是您使用的是base64编码的数据URI。以这种方式编码的图像大约是实际图像数据本身的150%。换句话说,你为已经紧张的情况增加了更大的压力。相反,您应该有一个返回图像数据的操作,如:

public ActionResult GetImage(int id)
{
    var image = db.Images.Find(id);
    if (image == null)
    {
        return new HttpNotFoundResult();
    }

    return File(image.FileData, image.FileType);
}

通过缓存数据库查询结果甚至整个响应,您可以在这里获得一些创意,但请注意,您需要大量的RAM,因为您将要存储大量的那里的图像数据。

第三,首先是使用数据库存储图像数据的问题。仅仅因为数据库提供blob类型,并不意味着你需要使用它。最高效的方法始终是直接从文件系统提供服务,因为IIS可以直接提供静态文件,而不涉及所有ASP.NET机制。不是将图像数据存储在数据库中,而是将图像写入文件系统位置,然后仅将图像的路径存储在数据库中。然后,您可以通过实际将所有图像卸载到CDN来进一步优化,确保超快速交付并从服务器上卸下几乎所有负载。