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");

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

Спасибо.

EDIT

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

Обновление в лицо недавней активности (8 Набор 2012)

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

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

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

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

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

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

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

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

И если вы рассматриваете такой вариант, я думаю, что вам, вероятно, будет легче построить REST Style Web API для ваших собственных нужд.

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

12 25

12 ответов:

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

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

Вы используете ISA или кальмар?

Что такое код ответа http для вашего запроса?

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

Правка:

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

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

Пойти еще ниже: Как создать HTTP-запрос вручную .Чистая?

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

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

Для ex -

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

Попробуйте NoCacheNoStore:

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

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

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

Пример: http://www.someserver.com/?param1=val1&ThisIsRandom=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 оба используют один и тот же кэш.

У меня была аналогичная проблема с 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() }

Использование 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 page not found, вы не можете знать, что веб-страница теперь вообще не существует.

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

  • установить заголовок как ("Cache-Control", "no-cache")
  • установить " запрос.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
        {

        }
    }
}

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

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

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