有没有办法强制WebClient不返回缓存数据?

9
我正在像这样从Web服务器目录中检索图像:

        WebClient webClientImgDownloader = new WebClient();
        webClientImgDownloader.OpenReadCompleted += new OpenReadCompletedEventHandler(webClientImgDownloader_OpenReadCompleted);
        if(uriIndex < uris.Count())
            webClientImgDownloader.OpenReadAsync(new Uri(uris[uriIndex], UriKind.Absolute));

但是我注意到,如果我删除了图片,Silverlight 仍然会像图片仍在那里一样检索它。
然后我在 FireFox 中输入图片的 URL,也能看到图片,但当我点击“重新加载”时,它会给我适当的错误提示,即图片不存在。然后当我再次运行我的 Silverlight 应用程序时,它也会适当地给我一个错误提示,即图片不存在,就好像浏览器在某个地方清除了缓存标记。
那么,我该如何通过 WebClient 在代码中进行“刷新”,以便如果服务器上的图片突然不存在,Silverlight 不会继续给我它的缓存副本?

WebClient不会返回缓存数据。它返回服务器和任何缓存代理提供的数据。你需要让服务器不发送你不想接收的数据。 - John Saunders
1
@John:实际上,在这种情况下,我怀疑根本没有进行任何实际请求。WebClient将使用浏览器堆栈,并从本地缓存中提供内容,而不是向服务器发出请求。 - AnthonyWJones
@Anthony:我不知道它会重复使用那么多的浏览器堆栈。你有参考资料可以证明是这样做的吗? - John Saunders
1
@John:默认情况下,Silverlight的HTTP堆栈与宿主浏览器高度集成,请参见:http://msdn.microsoft.com/en-us/library/dd920295(v=VS.95).aspx和http://msdn.microsoft.com/en-us/library/cc838250(v=VS.95).aspx。 - AnthonyWJones
@Anthony:抱歉,我错过了“Silverlight”标签。 - John Saunders
这是一个非常好的问题。 - VoodooChild
3个回答

7

这是一个棘手的问题,因为缓存通常是由网站头部未指定no-cache引起的。我发现在过去,处理这些缓存问题最简单的方法就是提供一个随机的查询字符串参数,这样Web服务器会将每个请求解释为新请求。

如果您当前正在请求www.domain.com/image.jpg,则尝试www.domain.com/image.jpg?rand=XXXX,其中XXXX是在您的服务器端代码中生成的随机值。


1
使用随机查询字符串的问题在于它总是会强制下载资源,因为从HTTP的角度来看,它是一个不同的资源,无法判断当前缓存版本是否是最新版本并可以重用。这可能会对应用程序的性能产生不利影响。 - AnthonyWJones
+1 对于随机查询字符串的想法表示赞同,只要注意到性能不是问题。这似乎会强制它始终给您准确的响应,您可以将其设置为选项,以便在开发时包括随机字符串,然后当您的网站上线并且数据已设置好时,可以删除它以获得更好的性能。 - Edward Tanguay
Edward,这正是我想做的。通常我使用String.Format("{0}{1}", url, (HttpContext.Current.IsDebuggingEnabled) ? randomParam : String.Empty)。我发现这有助于我绕过IIS缓存非ISAPI注册元素(如js文件等)。 - Brian Scott
1
如果它能工作,那就行了。个人认为这是一种丑陋的黑客技巧,如果可能的话应该避免使用。但是你是对的,如果你无法控制图像源站点并且你不信任站点自己的缓存规范(或者他们没有提供),那么你可能不得不采取这种方法。 - AnthonyWJones

4
你需要决定网站上各种内容的缓存策略。如果你必须确保每次请求时都呈现最新状态,请确保服务器适当配置响应标头。在这种情况下,请确保图像(或更可能是保存一组图像的文件夹)上指定了header:Cache-Control: max-age=0
通过设置max-age=0,您将导致浏览器尝试重新获取图像,但它会向服务器通报其缓存中存在的任何现有版本的图像。这给服务器提供了机会发送状态 404,因为图像已被删除,304,因为图像仍然存在且未更改,因此可以使用缓存的版本,或者200,因为图像已更改,后者会带有新版本。

这有点假设他对所请求的服务器具有控制权。我想象一下,考虑到他正在使用WebClient获取图像,更可能的是他正在使用WebClient将它们下载下来,因为它们是远程/超出他的控制范围? - Brian Scott
@Brian:不想吹毛求疵,但他说“如果我删除图像”,暗示他控制着 Web 服务器。 - Evan

0

这是我的解决方案:

return new BitmapImage(new Uri(Mang.Communication.ServicePathUrl + "Icon.aspx?location=" + value.imageParameter + "&originalSize=true" +  "?" +  System.DateTime.Now.ToString(), UriKind.Absolute));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接