2011-07-08 187 views
1

我的情况是这样的:渲染图像在asp.net MVC

我创建一个返回三列基于存储过程O自定义报告(为person_id [长],名[VARCHAR(100)],年龄[INT ],照片[图片])。这些是我的数据库表中的列和类型。

现在我为报告的每个图像使用类似的东西。

<img src="<%= Url.Action("ShowImage", "Reports", new {personId = result["PERSON_ID"]}) %>" /> 

与ShowImage是

public virtual ActionResult ShowImage(long? personId) 
    { 
      try 
      { 
       if (personId.HasValue) 
       { 
        byte[] imageArray = StudentClient.GetPersonPhotoById(personId.Value); 
        if (imageArray == null) 
         return File(noPhotoArray, "image/jpg"); 

        #region Validate that the uploaded picture is an image - temporary code 

        // Get Mime Type 
        byte[] buffer = new byte[256]; 
        buffer = imageArray.Take(imageArray.Length >= 256 ? 256 : imageArray.Length).ToArray(); 
        var mimeType = UrlmonMimeType.GetMimeType(buffer); 

        if (String.IsNullOrEmpty(mimeType) || mimeType.IndexOf("image") == -1) 
         return File(noPhotoArray, "image/jpg"); 

        #endregion 

        return File(imageArray, "image/jpg"); 
       } 
      } 
      catch 
      { 
       return File(noPhotoArray, "image/jpg"); 
      } 
    } 

我想用某种替代的,因为这是非常stresful由于该ShowImage()调用服务方法StudentClient.GetPersonPhotoById(personId.Value );对于每一张照片来说,这意味着分配给服务和数据库的呼叫也是这样。

我想实际使用该照片列返回一个字节数组,而不是通过ShowImage控制器方法使用Person_id列。

这将实际上减少对服务的调用次数为0,并使用图像列中的实际数据。这看起来很简单,但我很难找到解决方案。

谢谢!

回答

3

最简单的解决方案 - 使用OutputCache。此外,您可以将缓存位置设置为客户端,并且浏览器在下载后会缓存图像。 VaryByParam将为您提供根据personId缓存图像的功能。

0

有一种非常简洁的技术,您可以通过Web服务器将二进制数据直接从SQL Server传输到客户端。

这是我做的代码:

public void StreamFile(Stream stream) 
    { 
     DbDataReader dr = LoadDbStream(); 
     if (!dr.Read()) 
      return; 

     const int BUFFERSIZE = 512; 
     byte[] Buffer = new byte[BUFFERSIZE]; 
     long StartIndex = 0; 
     long Read = dr.GetBytes(0, StartIndex, Buffer, 0, BUFFERSIZE); 

     while (Read == BUFFERSIZE) 
     { 
      stream.Write(Buffer, 0, BUFFERSIZE); 

      StartIndex += BUFFERSIZE; 
      Read = dr.GetBytes(0, StartIndex, Buffer, 0, BUFFERSIZE); 
     } 
     stream.Write(Buffer, 0, (int)Read); 
    } 

    private DbDataReader LoadDbStream() 
    { 
     DbCommand cmd = Cms.Data.GetCommand("SELECT Data FROM CMS_Files WHERE FileId = @FileId", "@FileId", Id.ToString()); 
     cmd.CommandType = System.Data.CommandType.Text; 

     cmd.Connection.Open(); 
     return cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection); 
    } 

Command对象是一个普通的命令对象。关键部分是CommandBehavior.SequentialAccess标志,因为这使得sql server只在需要时发送数据。因此,您只能按查询中指定的顺序读取列。另一点是流应该是输出流从请求&开关输出缓冲关闭。

将此与outputcaching结合起来,可以减少服务器上的内存负载。

Simon

0

您可以使用它作为图像的源代码。

src="data:image/jpg;base64,<%= System.Convert.ToBase64String(result["PHOTO"] as byte[]) %>" 
+0

只有当他们是小图像,甚至那么有用性是有争议的。您绕过了用户和服务器之间的所有缓存机制(服务器,代理,浏览器)。 –