C#WebClient禁用缓存

美好的一天。

我在我的C#应用​​程序中使用WebClient类,以便每分钟下载相同的文件,然后应用程序执行简单的检查以查看文件是否已更改,以及它是否确实对其执行了操作。

好吧,因为这个文件每分钟下载一次, WebClient缓存系统就会缓存文件,而不是再次下载文件,只是简单地从缓存中获取文件,这样就会检查下载的文件是否是新文件。

所以我想知道如何禁用WebClient类的缓存系统。

我试过了。

 Client.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache); 

我也试过标题。

 WebClient.Headers.Add("Cache-Control", "no-cache"); 

没有用。 那我怎么能禁用缓存呢?

谢谢。

编辑

我还尝试了以下CacheLevelsNoCacheNoStoreBypassCacheReload 。 没有效果,但是如果我重新启动计算机,缓存似乎被清除,但我不能每次都重新启动计算机。

面对最近的活动更新(8集2012)

标记为已接受的答案解决了我的问题。 简单来说,我使用套接字下载文件,这解决了我的问题。 基本上是对所需文件的GET请求,我不会详细介绍如何操作,因为我相信你可以在SO上找到很多“如何”,以便自己做同样的事情。 虽然这并不意味着我的解决方案也是最适合您的,但我的第一个建议是阅读其他答案,看看是否有用。

好吧无论如何,因为这个问题已经看到了最近的一些活动,我想添加这个更新,以包括一些我认为应该考虑面临类似问题的人应该考虑的提示或想法,他们尝试了他们可以想到的一切,并且确定问题没有撒谎他们的代码。 可能是大多数情况下的代码,但有时候我们只是不太看,只要走几分钟后再回来,你可能会看到它是空白范围,就像它是最明显的一样。第一名。

无论哪种方式,如果您确定,那么在这种情况下,我建议检查天气您的请求通过其他具有缓存function的设备(计算机,路由器,代理,…),直到它到达预定目的地。

考虑到大多数请求都通过之前提到的一些此类设备,更常见的是路由器,除非您通过服务提供商网络直接连接到Internet。

有一段时间我自己的路由器正在缓存文件,奇怪我知道,但事实就是如此,每当我重新启动它或直接连接到Internet时,我的缓存问题就消失了。 并且没有任何其他设备连接到路由器可以被指责,只有计算机和路由器。

顺便说一句,一般建议,虽然它主要适用于那些在公司开发计算机而不是自己的计算机上工作的人。 可以通过任何更改您的开发计算机运行各种缓存服务? 有可能的。

此外,考虑到许多高端网站或服务使用内容交付网络 (CDN),并且根据CDN提供商,无论何时更新或更改文件,此类更改都需要一些时间才能反映在整个网络中。 因此,您可能有可能要求提供可能处于更新中间的文件,并且最近的CDN服务器尚未完成更新。

在任何情况下 ,特别是如果你总是一遍又一遍地请求同一个文件,或者你找不到问题所在,那么如果可能的话,我建议你重新考虑你的方法,一次又一次地请求同一个文件,而是考虑构建一个简单的Web服务 ,以满足您首先考虑满足此类文件的需求。

如果您正在考虑这样的选项,我认为您可能会更容易根据自己的需要构建REST样式Web API 。

我希望这个更新在某种程度上对你有用,肯定会在我回来的时候。 祝您的编码工作顺利。

从上面我猜想你在其他地方有问题。 你能在服务器端记录http请求吗? 当你改变一些随机种子参数时你会得到什么?

也许SERVER缓存文件(如果日志显示请求确实是每分钟触发一次。

你使用ISA还是SQUID?

什么是您的请求的http响应代码?

我知道回答答案可能不受欢迎,但评论不允许我这么多文字:)

编辑:

无论如何,使用HttpRequest对象而不是WebClient ,并希望(如果你把疑虑放在WebClient )一切都将得到解决。 如果它没有用HttpRequest解决,那么问题确实在其他地方。

进一步完善:

更低: 如何在.Net中手动创建HTTP请求?

这是纯粹的套接字,如果问题仍然存在,那么打开一个新问题并标记为WTF 🙂

每次下载文件时,您都可以尝试将一些随机数附加到您的url,作为查询字符串的一部分 。 这确保了每次都是唯一的URL。

对于前

 Random random = new Random(); string url = originalUrl + "?random=" + random.Next().ToString(); webclient.DownloadFile(url, downloadedfileurl); 

试试NoCacheNoStore

永远不会通过使用缓存中的资源来满足请求,也不会缓存资源。 如果资源存在于本地缓存中,则会将其删除。 此策略级别向中间缓存指示应删除资源。 在HTTP缓存协议中,这是使用no-cache缓存控制指令实现的。

 client.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore); 

在某些情况下,网络调试软件可能会导致此问题。 为了确保您的url没有被缓存,您可以附加一个随机数作为最后一个参数,以使url唯一。 在大多数情况下,这个随机参数被服务器忽略(它尝试读取作为名称值对发送的参数)。

示例: http : //www.someserver.com/?param1 = val1&TheThisIsRandom = RandomValue

其中ThisIsRandom = RandomValue是添加的新参数。

我猜你将不得不使用webrequest / webresponse而不是webclient

  WebRequest request = WebRequest.Create(uri); // Define a cache policy for this request only. HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore); request.CachePolicy = noCachePolicy; WebResponse response = request.GetResponse(); //below is the function for downloading the file public static int DownloadFile(String remoteFilename, String localFilename) { // Function will return the number of bytes processed // to the caller. Initialize to 0 here. int bytesProcessed = 0; // Assign values to these objects here so that they can // be referenced in the finally block Stream remoteStream = null; Stream localStream = null; WebResponse response = null; // Use a try/catch/finally block as both the WebRequest and Stream // classes throw exceptions upon error try { // Create a request for the specified remote file name WebRequest request = WebRequest.Create(remoteFilename); // Define a cache policy for this request only. HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore); request.CachePolicy = noCachePolicy; if (request != null) { // Send the request to the server and retrieve the // WebResponse object response = request.GetResponse(); if (response != null) { if (response.IsFromCache) //do what you want // Once the WebResponse object has been retrieved, // get the stream object associated with the response's data remoteStream = response.GetResponseStream(); // Create the local file localStream = File.Create(localFilename); // Allocate a 1k buffer byte[] buffer = new byte[1024]; int bytesRead; // Simple do/while loop to read from stream until // no bytes are returned do { // Read data (up to 1k) from the stream bytesRead = remoteStream.Read(buffer, 0, buffer.Length); // Write the data to the local file localStream.Write(buffer, 0, bytesRead); // Increment total bytes processed bytesProcessed += bytesRead; } while (bytesRead > 0); } } } catch (Exception e) { Console.WriteLine(e.Message); } finally { // Close the response and streams objects here // to make sure they're closed even if an exception // is thrown at some point if (response != null) response.Close(); if (remoteStream != null) remoteStream.Close(); if (localStream != null) localStream.Close(); } // Return total bytes processed to caller. return bytesProcessed; } 
 client.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache); 

应该管用。 运行代码之前,只需确保清除缓存并删除Internet Explorer中的任何临时下载文件,因为System.Net和IE都使用相同的缓存。

我使用webClient在powershell上遇到了类似的问题,在切换到使用webRequest之后也存在。 我发现的是套接字被重用并导致各种服务器/网络端缓存(在我的情况下,负载均衡器在使用https方面尤其成问题)。 解决这个问题的方法是在webrequest对象中禁用keepalive和可能的管道,如下所示,这会强制为每个请求添加一个新套接字:

 #Define Funcs Function httpRequest { param([string]$myurl) $r = [System.Net.WebRequest]::Create($myurl) $r.keepalive = 0 $sr = new-object System.IO.StreamReader (($r.GetResponse()).GetResponseStream()) $sr.ReadToEnd() } 

使用HTTPRequest绝对是您问题的正确答案。 但是,如果您希望保持WebBrowser / WebClient对象不使用缓存页面,则不应仅包括"no-cache"而应包括所有这些标头:

     

在IE11中,直到我包含最后两个中的一个或两个,它才对我有效。

这里的所有方法似乎都无法解决问题:如果网页曾经可以访问并且现在已从服务器中删除,则HttpWebResponse.GetResponse()方法将为您提供对缓存副本的响应,该副本以“足够的时间段”开头时间已经过去了,或者你重新启动计算机,它不会触发404页面找不到错误的预期exception,你现在根本不知道网页现在根本不存在。

我尝试了一切:

  • 设置标题(“Cache-Control”,“no-cache”)
  • 将“request.CachePolicy”设置为“noCachePolicy”
  • 删除IE tem / history文件。
  • 使用没有路由器的有线互联网……….不工作!

幸运的是,如果网页已更改其内容, HttpWebResponse.GetResponse()将为您提供一个新页面以反映更改。

检查您的价格是否受到限制! 我从一个nginx服务器回来了:

403禁止

超出限额,请在24小时内再试一次。

这是我正在使用的程序(C#)

 using System; using System.IO; using System.Net; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { DownloadFile(); Console.ReadLine(); } public static void DownloadFile() { var downloadedDatabaseFile = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); Console.WriteLine(downloadedDatabaseFile); var client = new WebClient(); client.DownloadProgressChanged += (sender, args) => { Console.WriteLine("{0} of {1} {2}%", args.BytesReceived, args.TotalBytesToReceive, args.ProgressPercentage); }; client.DownloadFileCompleted += (sender, args) => { Console.WriteLine("Download file complete"); if (args.Error != null) { Console.WriteLine(args.Error.Message); } }; client.DownloadFileAsync(new Uri("http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dats.gz"), downloadedDatabaseFile); } } } 

控制台打印出来:

 C:\Users\jake.scott.WIN-J8OUFV09HQ8\AppData\Local\Temp\2\tmp7CA.tmp Download file complete The remote server returned an error: (403) Forbidden. 

因为我使用以下内容:

 wclient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore); wclient.Headers.Add("Cache-Control", "no-cache"); 

我再也没有缓存文件了。

我还添加了我发现的这个函数,在每次调用之前删除IE临时文件:

 private void del_IE_files() { string path = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); //for deleting files System.IO.DirectoryInfo DInfo = new DirectoryInfo(path); FileAttributes Attr = DInfo.Attributes; DInfo.Attributes = FileAttributes.Normal; foreach (FileInfo file in DInfo.GetFiles()) { file.Delete(); } foreach (DirectoryInfo dir in DInfo.GetDirectories()) { try { dir.Delete(true); //delete subdirectories and files } catch { } } } 

如果您有访问Web服务器的权限,请打开Internet Explorer

Internet Explorer -> Internet Options -> Browsing History "Settings" -> Temporary Internet Files "never"

清除浏览器缓存,瞧,它会工作!