2014-03-31 57 views
1

我寫過一個圖像處理程序,它通過在滿足特定條件時發送304來實現客戶端緩存。爲了訪問不同的照片或登錄的人自己的照片,我們將處理程序按以下方式放在不同的頁面上。ASHX通用處理程序在刷新頁面之前不會觸及(使用F5或刷新按鈕)

<img src="EmployeePhoto.ashx" /> 
<img src="EmployeePhoto.ashx?self" /> 
<img src="EmployeePhoto.ashx?default" /> 

的問題是,如果我通過點擊鏈接在第二次的影像已被緩存的頁面後,它並沒有擊中處理器(調試器不會命中)訪問任何頁面。但是,如果我用F5或刷新按鈕刷新該頁面,那麼只有它碰到處理程序並顯示我想要顯示的內容。

只有當我試圖用另一個參數如「& date =」+ CurrentDate來訪問它時,它會觸發處理程序,但它會殺死緩存的目的。

<img src="EmployeePhoto.ashx?default&date=03/31/14 00:00:00" /> //or something like that 

我知道代碼沒有問題,因爲它在被命中時效果很好。無論如何,這是代碼。

public void ProcessRequest(HttpContext context) 
{ 
    var isDefault = true; 
    var textIfModifiedSince = context.Request.Headers["If-Modified-Since"]; 
    context.Response.ClearHeaders(); 
    context.Response.Cache.SetCacheability(HttpCacheability.Public); 
    context.Response.Cache.SetExpires(DateTime.Now.AddMonths(6)); 
    try 
    { 
     var isOwn = false; 
     var user = /*Gets logged in user instance from service*/; 
     var employeeId = 0; 
     if (context.Request.QueryString.Count > 0) 
     { 
      if(context.Request.QueryString[0] == "self") 
      { 
       if (user != null) 
       { 
        employeeId = Convert.ToInt32(user.EmployeeId); 
        isOwn = true; 
       } 
      } 
      else if (!int.TryParse(context.Request.QueryString[0], out employeeId)) 
       employeeId = 0; 
     } 
     else 
     { 
      if (user != null) 
      { 
       employeeId = Convert.ToInt32(user.EmployeeId); 
       isOwn = true; 
      } 
     } 


     if (user != null && employeeId != 0) 
     { 
      var employee = GetEmployee(employeeId); 
      if (
       (!string.IsNullOrEmpty(textIfModifiedSince) && employee.Modify_Date == null) 
       || !string.IsNullOrEmpty(textIfModifiedSince) 
       && employee.Modify_Date != null 
       && employee.Modify_Date <= Convert.ToDateTime(textIfModifiedSince).AddMinutes(1)) 
      { 
       isDefault = false; 
       context.Response.Cache.SetLastModified(Convert.ToDateTime(textIfModifiedSince)); 
       context.Response.Status = "304 Not Modified"; 
       HttpContext.Current.ApplicationInstance.CompleteRequest(); 
       return; 
      } 
      if (
       employee != null 
       && !string.IsNullOrEmpty(employee.Picture) 
       && (isOwn || employee.LocationID != null) 
       && (isOwn || HasRequiredRoles)) 
      { 
       var path = context.Server.MapPath("~//" + EmployeePhotoPath); 
       if (!Directory.Exists(path)) 
        Directory.CreateDirectory(path); 
       var fileName = employee.Picture; 
       var destinationPath = 
        context.Server.MapPath("~//" + EmployeePhotoPath).ToString(CultureInfo.InvariantCulture); 
       if (File.Exists(destinationPath + fileName)) 
       { 
        isDefault = false; 
        context.Response.Cache.SetLastModified(employee.Modify_Date > DateTime.Now ? DateTime.Now : (employee.Modify_Date ?? DateTime.Now)); 
        context.Response.ContentType = GetContentType(employee.Picture); 
        context.Response.WriteFile(EmployeePhotoPath + employee.Picture); 
        HttpContext.Current.ApplicationInstance.CompleteRequest(); 
        return; 
       } 
       isDefault = false; 
       DownloadFromSFTP(path, employee.Picture, user, employeeId.ToString(CultureInfo.InvariantCulture)); 
       context.Response.Cache.SetLastModified(employee.Modify_Date > DateTime.Now ? DateTime.Now : (employee.Modify_Date ?? DateTime.Now)); 
       context.Response.ContentType = GetContentType(employee.Picture); 
       context.Response.WriteFile(EmployeePhotoPath + employee.Picture); 
       HttpContext.Current.ApplicationInstance.CompleteRequest(); 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     Log.Debug("Photo Handler Failed.", ex); 
    } 
    finally 
    { 
     if (isDefault) 
     { 
      if (!string.IsNullOrEmpty(textIfModifiedSince)) 
      { 
       context.Response.Cache.SetLastModified(Convert.ToDateTime(textIfModifiedSince)); 
       context.Response.Status = "304 Not Modified"; 
       HttpContext.Current.ApplicationInstance.CompleteRequest(); 
      } 
      context.Response.Cache.SetLastModified(DateTime.Now); 
      context.Response.ContentType = GetContentType("images/avatar.gif"); 
      context.Response.WriteFile("images/avatar.gif"); 
      HttpContext.Current.ApplicationInstance.CompleteRequest(); 
     } 
    } 
} 

ADDITION: 在以下情況下會發生此問題。

  1. 用戶通過訪問EmployeePhoto.ashx訪問圖像?Eid的= 20349
  2. 管理員再次改變爲Eid的照片= 20349
  3. 用戶訪問的頁面(未清涼但一些鏈路訪問頁)

頁面上的緩存圖像帶來舊圖像,如果它已經擊中處理程序,那麼情況已經在那裏處理,但它沒有,頁面顯示緩存版本本身。我只在鉻上檢查過。

+0

如果你想要加載圖像,而不是隻是第一次在[這篇文章]有一些想法(http://stackoverflow.com/questions/13369379/how-do-i-expire-a-cached -image-without-hitting-f5) – Pete

+0

我訪問了@Pete這個問題,我已經嘗試過那裏提到的解決方案。但它會殺死緩存的目的,因爲每次它將發佈一個新的「If-Modified-Since」 –

+0

這是一個「Bekaar sawaal」,順便說一句,「614」kese karli itni聲譽? –

回答

1

使用本身是錯誤的。

你想要從同一網址登錄的人的獨特照片?這是不可能的

一旦URL被擊中,瀏覽器將緩存它。

我的解決方案是將用戶ID追加到處理程序。

<img src="EmployeePhoto.ashx?uid=1" /> 
<img src="EmployeePhoto.ashx?self&uid=1" /> 
<img src="EmployeePhoto.ashx?default&uid=1" /> 

這樣,broswer會發出請求並得到響應和將緩存它,並使用高速緩存以來的網址都符合特定用戶。

看到你的加法。我建議在數據庫中存儲一個標誌,無論管理員是否改變了圖像。然後,如果管理員更改了圖片,那麼您可以修改標題。現在,從db中刪除標誌,所以下一次,你不會這樣做。

+0

謝謝你的回答。我用一個場景更新了這個問題。請閱讀場景。這個答案不回答我的問題,所以我不能將它標記爲一個。 –