在ASP.NET MVC中显示图像的不同方式以及何时使用哪种方法

sid*_*rth 7 c# asp.net-mvc asp.net-mvc-4

我正在使用ASP.NET MVC4构建一个上传/显示图像的网站,并找到了一些如何显示图像的方法,主要是以下内容 -

1)将图像作为文件本地存储在服务器上,并使用相对路径在页面上显示它.

 //ImageFile is a property which holds a path to the image in the model
 <img src="@item.ImageFile" />

 When the page is rendered, this becomes a path like - <img src="/Content/Images/Jellyfish.jpg" />      
Run Code Online (Sandbox Code Playgroud)

2)将图像存储为字节数组并使用控制器操作进行检索 -

//Use a controller action (GetImg) to get the URL of the image
<img src="@Url.Action("GetImg", "ViewPhotos", new { id = item.ID })" alt="Image" />  

When the page is rendered, this becomes a path like - <img src="/ViewPhotos/GetImg/4" alt="Image" />    
Run Code Online (Sandbox Code Playgroud)

3)将图像存储为字节数组并直接在视图中进行检索 -

//Directly re-construct the image in the view from the byte array (Image property of the model)
<img src="@String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(item.Image))" />  

When the page is rendered, this becomes a path like - <img src="data:image/jpg;base64,/9j/4AAQSkZJRgABAgEA....<long string> .../>
Run Code Online (Sandbox Code Playgroud)

我的问题是 -

1)1和2有什么区别?

1直接提供文件路径,2提供URL.它们在背景中是相同的还是比另一种更好的方法?

我在这里查了一下,它说 - Url.Action将构建动作的路径,返回一个url,而不是执行动作的结果.那么什么时候检索结果?

2)当使用3对1或2时是否会对性能产生影响?

3)当图像尺寸小(小于1MB)或大时,应采用哪种方法?

如果您能指出任何可以提供帮助的链接,请高兴.谢谢.

代码 -

//模型

public class Photo
{
  public int ID { get; set; }
  public string ImageFile { get; set; }
  public byte[] Image { get; set; }
  public string Caption { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

//控制器

public FileContentResult GetImg(int id)
{
    byte[] byteArray = db.Photos.Find(id).Image;
    if (byteArray != null)
    {
        return new FileContentResult(byteArray, "image/jpeg");
    }
    else
    {
         return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

//查看(方法2)

@model IEnumerable<MyPhotoLibrary.Models.Photo>
@foreach (var item in Model) {
<tr>
  <td>
    <img src="@Url.Action("GetImg", "ViewPhotos", new { id = item.ID })" alt="Image" />
  </td>
</tr>
}
Run Code Online (Sandbox Code Playgroud)

//查看(这是方法3)

@model IEnumerable<MyPhotoLibrary.Models.Photo>
@foreach (var item in Model) {
<tr>
  <td>
    <img src="@String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(item.Image))" />
  </td>
</tr>
}
Run Code Online (Sandbox Code Playgroud)

ana*_*der 14

我最近自己查了一下,并且看到了微软的研究论文To BLOB Or Not To BLOB,它将数据库中存储文件(如图像)的性能与传统文件系统的二进制数据进行了比较.

调查结果大致总结如下:

  • 小文件(大小> 256KB)最好存储为数据库中的字节数组(第二个和第三个选项),从中可以快速检索它们并提供给用户.
  • 大文件(大小> 1MB左右)最好存储在文件系统中(您的第一个选项),因为较大的文件会导致大型数据库blob的吞吐量和碎片严重恶化
  • 256KB到1MB之间(大致;范围模糊,取决于您的确切设置)性能取决于文件可能被编辑或覆盖的次数; 通常,数据库在使用静态文件时表现更好,而文件系统在使用频繁更改的文件保持高吞吐量和低碎片方面要好得多.

选项之间的其他差异:

选项1要求您的应用程序对图像所在的任何文件夹具有读取权限,如果图像是由用户上载或编辑的,则应用程序也需要对该文件夹具有写入权限.如果您正在共享托管(特别是在廉价或免费托管计划上)或者您的系统管理员特别偏执,这可能会很棘手.

选项2需要从客户端到服务器的更多调用来获取所有数据; 这可能看起来像是一件坏事,但它确实将页面加载分解为可能实际有用的块 - 页面(没有图像)将在第一次调用时加载,然后图像将被单独请求,如果其中一个需要一段时间,或者有某种错误,然后页面的其余部分应该不受影响,这很好.正如jgauffin在评论中指出的那样,此选项允许您为图像设置缓存,因此浏览器可以通过仅在更改时重新下载来保存带宽.

选项3要求客户将整批货物装入一个,这可能需要一段时间.它还将字节数组的处理转移到客户端,这可能是智能手机或低端上网本等低功耗客户端的问题.如果图像很大,最好使用服务器的CPU电源来实际处理从字节数组到图像文件的转换.正如jgauffin在评论中指出的那样,这也不能很好地与缓存相关 - 如果视图的HTML的任何部分发生变化,浏览器将不得不再次下载图像

此外,这可能与您的具体情况无关,但通过单独调用加载图像可让您在这些操作中执行其他操作,例如写入调试日志或在幕后执行其他一些内务处理.

  • +1选项2优于选项3,因为后者的图像缓存很难,因为每次更改视图(或图像本身)时缓存都将失效.Base64还需要一些额外的处理 (2认同)
  • 是的,缓存也值得一提.在选项2中,浏览器将识别出他们正在进行GET并获取图像,这些图像可以在多个页面中缓存和重用; 在选项3中,他们只看到他们必须处理的大量base64字符串. (2认同)