C# WebClient отключить кеш

Добрый день.

Я использую WebClient Класс в моем приложении C# для загрузки одного и того же файла каждую минуту, а затем приложение выполняет простую проверку, чтобы увидеть, был ли файл изменен, и если он делает что-то с ним.

Ну, так как этот файл загружается каждую минуту WebClient система кэширования кэширует файл, и не загружает файл снова, просто получает его из кэша, и это мешает проверять, является ли загруженный файл новым.

Поэтому я хотел бы знать, как можно отключить систему кэширования WebClient учебный класс.

Я пробовал.

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

Я также попробовал заголовки.

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

Не сработало. Итак, как я могу отключить кэш навсегда?

Благодарю.

РЕДАКТИРОВАТЬ

Я также попробовал следующее CacheLevels: NoCacheNoStore, BypassCache, Reload, Никакого эффекта, однако, если я перезагружаю свой компьютер, кажется, что кэш очищен, но я не могу каждый раз перезагружать компьютер.

ОБНОВЛЕНИЕ перед лицом недавней деятельности (8 Set 2012)

Ответ, помеченный как принятый, решил мою проблему. Проще говоря, я использовал Sockets для загрузки файла, и это решило мою проблему. В основном это GET-запрос для нужного файла, я не буду вдаваться в подробности о том, как это сделать, потому что я уверен, что вы можете найти множество "как" прямо здесь, на SO, чтобы сделать то же самое самостоятельно. Хотя это не означает, что мое решение также является лучшим для вас, мой первый совет - прочитать другие ответы и посмотреть, будут ли они полезны.

Ну, в любом случае, поскольку эти вопросы стали свидетелями некоторой недавней активности, я подумал о том, чтобы добавить это обновление, чтобы включить некоторые подсказки или идеи, которые, по моему мнению, должны быть рассмотрены теми, кто сталкивается с похожими проблемами, которые испробовали все, что могли придумать, и уверены, что проблема не ' ложь со своим кодом. Скорее всего, это код для большинства случаев, но иногда мы просто не видим его, просто прогуляйтесь и вернитесь через несколько минут, и вы, вероятно, увидите его в упор, как это было наиболее очевидной вещью в первое место.

В любом случае, если вы уверены, то в этом случае я советую проверять, проходит ли ваш запрос через какое-либо другое устройство с возможностями кэширования (компьютеры, маршрутизаторы, прокси-серверы...) до тех пор, пока оно не достигнет назначенного пункта назначения.

Учтите, что большинство запросов проходят через некоторые из упомянутых выше устройств, чаще всего через маршрутизаторы, если, конечно, вы напрямую не подключены к Интернету через сеть поставщика услуг.

Однажды мой собственный маршрутизатор кэшировал файл, странно, я знаю, но это было так, когда я перезагружал его или подключался напрямую к Интернету, моя проблема с кэшированием исчезала. И нет, не было никакого другого устройства, связанного с маршрутизатором, который может быть обвинен, только компьютер и маршрутизатор.

И, между прочим, общий совет, хотя он в основном относится к тем, кто работает в компьютерах своей компании, а не на собственных. Могут ли какие-либо изменения на вашем компьютере разработки работать с какой-либо службой кэширования? Это возможно.

Кроме того, учтите, что многие высокопроизводительные веб-сайты или службы используют сети доставки контента (CDN), и, в зависимости от поставщика CDN, при каждом обновлении или изменении файла такие изменения отражаются во всей сети. Следовательно, возможно, вам не повезло запросить файл, который может находиться в середине обновления, а ближайший к вам сервер CDN не завершил обновление.

В любом случае, особенно если вы всегда запрашиваете один и тот же файл снова и снова или если вы не можете найти, в чем заключается проблема, тогда, если это возможно, я советую вам пересмотреть свой подход к запросу одного и того же файла раз за разом, и вместо этого посмотрите на создание простого веб-сервиса, чтобы удовлетворить потребности, которые вы сначала подумали об удовлетворении такого файла.

И если вы рассматриваете такую ​​возможность, я думаю, вам, вероятно, будет проще создать веб-API REST Style для ваших собственных нужд.

Я надеюсь, что это обновление в какой-то мере пригодится вам, конечно, оно будет для меня, пока я буду. Желаем удачи в ваших усилиях по кодированию.

12 ответов

Решение

Исходя из вышесказанного, я бы догадался, что у вас есть проблемы где-то еще. Можете ли вы протоколировать http запросы на стороне сервера? Что вы получаете, когда вы изменяете какой-то случайный начальный параметр?

Возможно, SERVER кэширует файл (если журнал показывает, что запрос действительно запускается каждую минуту.

Вы используете ISA или SQUID?

Что такое http код ответа на ваш запрос?

Я знаю, что ответы с ответами могут быть не популярны, но комментарии не позволяют мне так много текста:)

РЕДАКТИРОВАТЬ:

Во всяком случае, используйте HttpRequest объект вместо WebClientи, надеюсь, (если вы сомневаетесь WebClient) все будет решено. Если это не было решено с HttpRequestтогда проблема действительно в другом.

Дальнейшее уточнение:

Идите еще ниже: как мне вручную создать HTTP-запрос в.Net?

Это чистые сокеты, и если проблема не устранена, откройте новый вопрос и отметьте его WTF:)

Вы можете попробовать добавить какое-либо случайное число к вашему URL как часть строки запроса при каждой загрузке файла. Это гарантирует, что URL уникальны каждый раз.

Для бывших

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

Пытаться NoCacheNoStore:

Никогда не удовлетворяет запрос, используя ресурсы из кэша и не кэширует ресурсы. Если ресурс присутствует в локальном кэше, он удаляется. Этот уровень политики указывает промежуточным кэшам, что они должны удалить ресурс. В протоколе HTTP-кэширования это достигается с помощью директивы управления без кэширования.

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

В некоторых случаях этой проблемой может быть программное обеспечение для сетевой отладки. Чтобы убедиться, что ваш URL не кэшируется, вы можете добавить случайное число в качестве последнего параметра, чтобы сделать URL уникальным. Этот случайный параметр в большинстве случаев игнорируется серверами (которые пытаются прочитать параметры, отправленные в виде пар имя-значение).

Пример: http://www.someserver.com/?param1=val1&ThisIsRandom=RandomValue

Где ThisIsRandom = RandomValue - добавленный новый параметр.

У меня была похожая проблема с powershell при использовании webClient, которая также присутствовала после перехода на использование webRequest. Я обнаружил, что сокет используется повторно, и это вызывает все виды кэширования на стороне сервера / сети (и в моем случае балансировщик нагрузки оказался слишком проблематичным с https). Чтобы обойти это, нужно отключить keepalive и, возможно, конвейеризацию в объекте webrequest, как показано ниже, что приведет к созданию нового сокета для каждого запроса:

#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() }
client.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);

Должно сработать. Просто убедитесь, что вы очистили кеш и удалили все временные загруженные файлы в Internet Explorer, прежде чем запускать код как System.Net и IE оба используют один и тот же кеш.

Думаю, вам придется использовать 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;
    }

С помощью HTTPRequest безусловно, правильный ответ для вашей проблемы. Однако, если вы хотите, чтобы ваш объект WebBrowser/WebClient не использовал кэшированные страницы, вы должны включить не только "no-cache" но все эти заголовки:

<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache-control" content="no-store">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">

В IE11 он не работал для меня, пока я не включил один или оба из последних двух.

Кажется, что все методы здесь не могут решить проблему: если веб-страница когда-либо была доступна и теперь удалена с сервера, метод HttpWebResponse.GetResponse() даст вам ответ для кэшированной копии, начинающейся с "До достаточного периода времени". Прошло время, или вы перезагрузите компьютер, он НЕ вызовет ожидаемое исключение для ошибки 404 страница не найдена, вы не можете знать, что веб-страница теперь вообще не закрывается.

Я перепробовал все:

  • Установить заголовок как ("Cache-Control", "no-cache")
  • Установите "request.CachePolicy" в "noCachePolicy"
  • Удалить файлы тем / истории IE.
  • Используйте проводной интернет без роутера.......... НЕ РАБОТАЕТ!

К счастью, если веб-страница изменила свое содержание, HttpWebResponse.GetResponse() даст вам новую страницу, чтобы отразить изменения.

Если у вас есть доступ к веб-серверу, откройте Internet Explorer и перейдите на

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

Очистите кеш браузера и вуаля, все заработает!

Убедитесь, что вы не ограничены в скорости! Я получил это обратно с сервера 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
        {

        }
    }
}
Другие вопросы по тегам