2014-03-31 52 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

谢谢你的回答。我用一个场景更新了这个问题。请阅读场景。这个答案不回答我的问题,所以我不能将它标记为一个。 –