2011-07-08 234 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

只有當他們是小圖像,甚至那麼有用性是有爭議的。您繞過了用戶和服務器之間的所有緩存機制(服務器,代理,瀏覽器)。 –