views:

75

answers:

4

Hey all.

Right, my problem is that I need to replace an image that appears on every page of a site, which is fine, the problem is I want every user to see the new image and not a cached version of the old one. This is made especially difficult because I can’t make any code changes (far too many places to do it for it to be viable) so I need to replace the image on the server with a new one of the same name. Not only that but the pages are quite heavy so I don’t want to force the entire page to reload completely every time the page is requested.

Im thinking the best way would be to do something in IIS that will force the new image onto anybody who hasn’t got it already. The Last-Modified or Expires HTTP headers where my first stop but I can find a way to make them work against a single item rather than the entire page.

Any help/ideas would be fantastic!

Thanks, Tom.

A: 

I believe the only way to do it is to play with HTTP headers.

I see two options:

  1. Add headers to the file. I don't know IIS well, but I think they have such options;
  2. Replace your image with the script (php or C#), add headers manually in the code and send the image
Elalfer
A: 

IIS ought to be setting the last modified header and/or the etag based on the file itself, so if it's still caching it's possible that the browser is misbehaving, in which case you would be looking to set the No-Cache pragma. References: Microsoft KB reference, Section 14.9 of the HTTP1.1 spec

Elalfer's solution 2 would probably achieve a No-Cache pragma as a by-product.

Jim Downing
A: 

The HTTP headers always apply to only one item. In the case of those set on the page itself they apply only to the page and not to the linked resources.

Browsers and HTTP caches in the wild will have cached copies of this image already. There is no way to force them to reload the image without changing the URL of the image (which you've stated you cannot do).

If this is the only time you are changing this image, or you expect such changes to be infrequent, then just change the image and eventually the web will cache the new image. Browsers that check for updated versions will be notified by the web server that the timestamp has changed.

For making a more permanent change, you need to investigate how IIS is setting headers for your static files. I suspect that it sets all the headers uniformly for all files, but there may be a way to override the headers for a specific file. If not, you should be able to wrap the request for that url in a script which sets the headers before delivering the content. What you want to do, in this case, is set the Expires or max-age header so that browsers know how long they should keep this item in the cache. Note that these headers will only apply to future requests for this file.

Putting these headers in the pages themselves will not affect requests for the file. Be careful when adding cache-control headers as your site may not function properly if the wrong things are being cached too aggressively; alternatively your bandwidth may spike as things are not being cached which should be.

For future consideration you should make it possible to change the paths of static resources when the content changes. This makes it clear to a browser that the file is new because there will be nothing with that url in the path. For example:

www.yoursite.com/images/v1/logo.png

becomes

www.yoursite.com/images/v2/logo.png

once logo.png changes to v2. Then, in the pages where logo.png is referenced, you have code to automatically write the correct url in the page. This way each revision of the file has a unique name and thus never conflicts with any previously cached versions.

Mr. Shiny and New
Thanks for the help all. Ill let you know what I end up doing.
tomgriley
A: 

I had the same problem and found this solution:

$randy = md5( uniqid (rand(), 1) );

then make your image like:

$profile_img = "<img src='$imageLocation2?$randy' border='0'/>";

echo $profile_img;

This puts a random string on the end of the jpg file like ?3984289040823 so the source will look something like this:

<img src="example.jpg?3984289040823" />

The page thinks it is a new image and loads it.

Levani