web-dev-qa-db-fra.com

C # WebClient désactiver le cache

Bonne journée.

J'utilise la classe WebClient dans mon application C # afin de télécharger le même fichier toutes les minutes, puis l'application effectue une vérification simple pour voir si le fichier a été modifié et s'il fait quelque chose avec.

Eh bien, puisque ce fichier est téléchargé toutes les minutes, le système de mise en cache WebClient met en cache le fichier et ne le télécharge pas à nouveau, mais le récupère simplement dans le cache, ce qui empêche de vérifier si le fichier téléchargé est nouveau.

Je voudrais donc savoir comment désactiver le système de mise en cache de la classe WebClient.

J'ai essayé.

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

J'ai aussi essayé des en-têtes.

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

Cela n'a pas fonctionné aussi bien. Alors, comment puis-je désactiver le cache pour de bon?

Merci.

MODIFIER

J'ai également essayé les méthodes suivantes: CacheLevels: NoCacheNoStore, BypassCache, Reload. Aucun effet, cependant, si je redémarre mon ordinateur, le cache semble être effacé, mais je ne peux pas redémarrer l'ordinateur à chaque fois.

MISE À JOUR face à l'activité récente (Série 8 2012)

Le réponse marqué comme accepté a résolu mon problème. Pour le dire simplement, j'ai utilisé Sockets pour télécharger le fichier et cela a résolu mon problème. Fondamentalement, un GET demande pour le fichier souhaité, je ne vais pas entrer dans les détails sur la façon de le faire, parce que je suis sûr que vous pouvez trouver plein de "comment faire" ici même sur SO dans afin de faire la même chose. Bien que cela ne signifie pas que ma solution est également la meilleure pour vous, mon premier conseil est de lire les autres réponses et de voir si elles sont utiles.

Quoi qu’il en soit, comme ces questions ont fait l’objet d’une activité récente, j’ai pensé à ajouter cette mise à jour pour y inclure des astuces ou des idées qui, à mon avis, devraient être prises en compte par les personnes confrontées à des problèmes similaires qui ont essayé. tout ce qu'ils peuvent penser, et sont sûrs que le problème ne ment pas avec leur code. Probablement le code dans la plupart des cas, mais parfois nous ne le voyons pas très bien, nous allons simplement faire un tour et nous revenons au bout de quelques minutes, et vous le verrez probablement à bout portant comme si c'était le plus évident. chose en premier lieu.

Dans les deux cas, si vous en êtes sûr, dans ce cas, je vous conseille de vérifier si votre requête passe par un autre périphérique doté de fonctions de mise en cache (ordinateurs, routeurs, serveurs proxy, ...) jusqu'à ce qu'il atteigne la destination souhaitée. 

Considérez que la plupart des demandes passent par certains de ces dispositifs mentionnés plus haut, plus communément routeurs, à moins bien sûr que vous soyez directement connecté au Internet via votre fournisseur de services réseau.

À une époque, mon propre routeur mettait le fichier en cache, chose étrange, mais c’était le cas. Chaque fois que je le redémarrais ou que je me connectais directement à Internet, mon problème de mise en cache disparaissait. Et non, aucun autre périphérique connecté au routeur ne pouvait être blâmé, à part l'ordinateur et le routeur.

Et en passant, un conseil général, même s’il s’applique surtout à ceux qui travaillent dans les ordinateurs de développement de leur entreprise plutôt que chez eux. Est-ce que, par quelque changement que ce soit, votre ordinateur de développement peut exécuter un service de mise en cache? C'est possible.

De plus, considérez que de nombreux sites Web ou services haut de gamme utilisent Content Delivery Networks (CDN) et, en fonction du fournisseur de CDN, chaque fois qu'un fichier est mis à jour ou modifié, cela prend un certain temps pour que changements à refléter dans tout le réseau. Par conséquent, il pourrait être possible que vous ayez eu la malchance de demander un fichier qui pourrait être en cours de mise à jour, et le serveur CDN le plus proche de vous n'a pas fini de mettre à jour.

Dans tous les cas, spécialement si vous demandez toujours le même fichier, ou si vous ne trouvez pas où est le problème, alors si possible, je vous conseille de reconsidérer votre approche en demandant le même temps de fichier après coup, et au lieu de cela, envisagez de créer un simple service Web , pour répondre aux besoins auxquels vous avez pensé en premier lieu avec ce type de fichier.

Et si vous envisagez une telle option, je pense que vous aurez probablement plus de facilité à créer un RESTE Style API Web pour vos propres besoins.

J'espère que cette mise à jour vous sera utile, bien sûr que ce serait pour moi tout à l'heure. Bonne chance dans vos efforts de codage.

26
Fábio Antunes

De ce qui précède, je suppose que vous avez un problème ailleurs. Pouvez-vous enregistrer les requêtes http côté serveur? Qu'est-ce que vous obtenez lorsque vous modifiez un paramètre de graine aléatoire?

Peut-être que SERVER met le fichier en cache (si le journal montre que la demande est vraiment déclenchée toutes les minutes.

Utilisez-vous ISA ou SQUID?

Quel est le code de réponse http pour votre demande?

Je sais que répondre avec des réponses peut ne pas être populaire, mais le commentaire ne me permet pas autant de texte :)

MODIFIER:

Quoi qu'il en soit, utilisez HttpRequest object au lieu de WebClient et si tout va bien (si vous placez vos doutes dans WebClient) tout sera résolu. Si le problème n'a pas été résolu avec HttpRequest, alors le problème est vraiment IS ailleurs.

Raffinement supplémentaire:

Aller encore plus bas: Comment créer une demande HTTP manuellement en .Net?

Ce sont des sockets pures, et si le problème persiste, ouvrez une nouvelle question et identifiez-la en WTF :)

11

Vous pouvez essayer d’ajouter un nombre aléatoire à votre URL dans le cadre d’une chaîne de requête chaque fois que vous téléchargez le fichier. Cela garantit que les URL sont uniques à chaque fois. 

Par exemple

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

Essayez NoCacheNoStore :

Ne satisfait jamais une demande en utilisant des ressources du cache et ne met pas les ressources en cache. Si la ressource est présente dans le cache local, elle est supprimée. Ce niveau de stratégie indique aux caches intermédiaires qu'ils doivent supprimer la ressource. Dans le protocole de mise en cache HTTP, cela est réalisé à l'aide de la directive de contrôle de cache no-cache.

client.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore); 
10
KMån

Dans certains cas, le logiciel de débogage réseau peut être à l'origine de ce problème. Pour vous assurer que votre URL n'est pas mise en cache, vous pouvez ajouter un nombre aléatoire comme dernier paramètre pour que cette URL soit unique. Ce paramètre aléatoire est dans la plupart des cas ignoré par les serveurs (qui essaient de lire les paramètres envoyés sous forme de paires nom/valeur). 

Exemple: http://www.someserver.com/?param1=val1&ThisIandRandom=RandomValue

Où ThisIsRandom = RandomValue est le nouveau paramètre ajouté.

7
ivymike

Toutes les méthodes semblent ne pas résoudre un problème: Si une page Web a déjà été accessible et est maintenant supprimée du serveur, la méthode HttpWebResponse.GetResponse () vous donnera une réponse pour une copie en cache commençant par "Avant la période de temps suffisante s'est écoulée, ou vous redémarrez l'ordinateur, il ne déclenchera PAS l'exception attendue pour l'erreur de page non trouvée 404, vous ne pouvez pas savoir que la page Web n'existe pas du tout maintenant.

J'ai tout essayé:

  • Définir l'en-tête comme ("Cache-Control", "no-cache")
  • Définissez "request.CachePolicy" sur "noCachePolicy"
  • Supprimer IE fichiers tem/history. 
  • Utilisez Internet filaire sans routeur .......... NE FONCTIONNE PAS!

Heureusement, si la page Web a changé de contenu, HttpWebResponse.GetResponse() vous donnera une nouvelle page pour refléter le changement.

1
lbhl

J'ai eu un problème similaire avec PowerShell utilisant WebClient, qui était également présent après le passage à utiliser WebRequest. Ce que j’ai découvert, c’est que le socket est réutilisé et que toutes sortes de mises en cache côté serveur/réseau sont mises en cache (et dans mon cas, un équilibreur de charge gênait de manière particulièrement problématique avec https). Pour contourner ce problème, désactivez keepalive et éventuellement pipeler dans l'objet webrequest comme ci-dessous, ce qui forcera un nouveau socket pour chaque requête:

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

Devrait marcher. Assurez-vous simplement de vider le cache et de supprimer tous les fichiers téléchargés temporaires dans Internet Explorer avant que exécutant le code en tant que System.Net et IE utilisent tous deux le même cache.

1
Darin Dimitrov

Je suppose que vous devrez utiliser webrequest/webresponse plutôt que 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;
    }
1
Thakur

Utiliser HTTPRequest est définitivement la bonne réponse à votre problème. Toutefois, si vous souhaitez que votre objet WebBrowser/WebClient ne puisse pas utiliser les pages en cache, vous devez inclure non seulement "no-cache", mais également tous ces en-têtes:

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

Dans IE11, cela ne fonctionnait pas jusqu'à ce que j'inclus l'un ou l'autre des deux derniers. 

1
Daniel

depuis que j'utilise ce qui suit:

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

Je ne reçois plus de fichier en cache. 

J'ai également ajouté cette fonction trouvée pour supprimer IE les fichiers temporaires avant chaque appel:

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
        {

        }
    }
}
0
error

Vérifiez que votre taux n'est pas limité! Je récupérais ceci d'un serveur Nginx:

403 interdit

Taux limité dépassé, veuillez réessayer dans 24 heures.

Voici le programme que j'utilisais (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);
        }
    }
}

La console affiche:

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

Si vous avez accès au serveur Web, ouvrez Internet Explorer, allez à

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

Effacer le cache du navigateur et le tour est joué, ça va marcher!

0
efkah