This is what ETag, If-None-Match (or If-Not-Modified), and HTTP 304 resopnses are for.
If a file is sent with an ETag header and an acceptable caching policy, the browser will cache the file, and for each subsequent request will send the If-None-Match header.
The web server should check that the generated ETag of the file matches the If-None-Match request, and return either an HTTP 200 with the new content, or an HTTP 304 indicating that the cached version is still current.
Here is how I'm, using it in ASP.NET MVC 1.0:
public ActionResult ViewAvatar(long id)
{
UserAvatar avatar = this.AppManager.GetUserAvatar(id);
if (avatar != null && true)
{
byte[] imageData = avatar.Avatar.ToArray();
string eTag = LanLordzApplicationManager.CalculateMd5(imageData);
if (this.Request.Headers["If-None-Match"] == eTag)
{
return this.NotModified(
HttpCacheability.Public,
DateTime.Now.AddMinutes(2)
);
}
string mimeType = this.AppManager.GetImageMimeType(imageData);
return this.Image(
imageData,
mimeType,
HttpCacheability.Public,
DateTime.Now.AddMinutes(2),
eTag
);
}
else
{
return this.HttpError(404, this.View("NotFound"));
}
}