Question

Je CookieContainer extrait d'une HttpWebRequest / HttpWebResponse session nommée CookieJar . Je veux que mon application à stocker des cookies entre pistes, donc les cookies recueillis dans le CookieContainer sur une exécution du programme sera utilisé la prochaine exécution, aussi.

Je pense que la façon de le faire serait d'écrire en quelque sorte le contenu d'un CookieContainer sur le disque. Ma question est:

  • Comment pouvez-vous écrire un CookieContainer sur le disque ? Y at-il des fonctions intégrées pour cela, ou, sinon, quelles sont les approches personnes ont? Y a-t-il des classes disponibles pour simplifier cela?
  • Une fois que vous avez écrit un CookieContainer sur le disque, comment charger vous remettre dans pour ?

Mise à jour: La première réponse a suggéré sérialisation de la CookieContainer. Cependant, je ne suis pas très au courant de la façon de sérialisation et la désérialisation ces objets complexes. Pourriez-vous donner quelques exemples de code ? Il a été suggéré d'utiliser SOAPFormatter.

Était-ce utile?

La solution

Je l'ai pas essayé, mais il a l'attribut Serializable et peut donc être [de] sérialisé avec sérialisation binaire .net, par exemple SoapFormatter.

Voici le extrait de code que vous avez demandé.

var formatter = new SoapFormatter();
string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cookies.dat"); 

using (Stream s = File.Create (file))
    formatter.Serialize(s, cookies);                            
...
CookieContainer retrievedCookies = null;
using (Stream s = File.OpenRead (file))
    retrievedCookies = (CookieContainer) formatter.Deserialize(s);

En regardant msdn il semble SoapFormatter est maintenant dépréciée dans .NET 3.5 et il vous recommande d'utiliser BinaryFormatter. Dans le passé, j'ai trouvé SoapFormatter utile que le fichier est lisible qui aide au diagnostic quand désérialisation échoue! Ces formatteurs sont des changements sensibles à la version même dans la version de montage (donc si vous désérialiser avec une version du cadre de mise à niveau du cadre, il pourrait ne pas désérialiser, pas sûr), mais il y a des façons de contourner cela avec la propriété Binder si cela devient un problème. Je crois qu'ils sont principalement conçus pour persistence court terme / Remoting, mais ils pourraient être assez bon pour vous ici.

Le nouveau DataContractSerializer ne semble pas fonctionner avec si cela est hors.

Une alternative serait d'écrire une classe CookieContainerData à [de] sérialisation avec XmlSerializer et convertir manuellement entre ceci et CookieContainer.

Autres conseils

Ce problème me tracasse depuis des siècles, rien que je puisse trouver travaillé. Je l'ai travaillé, donc de mettre cette information dans le monde.

Répondre à l'aide BinaryFormatter:

    public static void WriteCookiesToDisk(string file, CookieContainer cookieJar)
    {
        using(Stream stream = File.Create(file))
        {
            try {
                Console.Out.Write("Writing cookies to disk... ");
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, cookieJar);
                Console.Out.WriteLine("Done.");
            } catch(Exception e) { 
                Console.Out.WriteLine("Problem writing cookies to disk: " + e.GetType()); 
            }
        }
    }   

    public static CookieContainer ReadCookiesFromDisk(string file)
    {

        try {
            using(Stream stream = File.Open(file, FileMode.Open))
            {
                Console.Out.Write("Reading cookies from disk... ");
                BinaryFormatter formatter = new BinaryFormatter();
                Console.Out.WriteLine("Done.");
                return (CookieContainer)formatter.Deserialize(stream);
            }
        } catch(Exception e) { 
            Console.Out.WriteLine("Problem reading cookies from disk: " + e.GetType()); 
            return new CookieContainer(); 
        }
    }

Il est intéressant d'avoir les cookies au format texte . En plus d'être en mesure d'être utilisé pour écrire sur le disque, il peut être utilisé à d'autres fins.

TRAVAUX POUR MOI!

Utilisez les fonctions de LoadCookiesFromFile et SaveCookiesToFile pour charger et écrire respectivement les cookies sur le disque.

Ou utiliser les fonctions de GetCookies et SetCookies à faire la même chose, mais pour le manipuler comme une chaîne.

CookieContainer cookieContainer = new CookieContainer();

void LoadCookiesFromFile(string path)
{
    SetCookies(cookieContainer, File.ReadAllText(path));
}

void SaveCookiesToFile(string path)
{
    File.WriteAllText(path, GetCookies(cookieContainer));
}

string GetCookies(CookieContainer cookieContainer)
{
    using (MemoryStream stream = new MemoryStream())
    {
        new BinaryFormatter().Serialize(stream, cookieContainer);
        var bytes = new byte[stream.Length];
        stream.Position = 0;
        stream.Read(bytes, 0, bytes.Length);
        return Convert.ToBase64String(bytes);
    }
}

void SetCookies(CookieContainer cookieContainer, string cookieText)
{
    try
    {
        var bytes = Convert.FromBase64String(cookieText);
        using (MemoryStream stream = new MemoryStream(bytes))
        {
            cookieContainer = (CookieContainer)new BinaryFormatter().Deserialize(stream);
        }
    }
    catch
    {
        //Ignore if the string is not valid.
    }
}

Une autre alternative consiste à utiliser la sérialisation Json ( Json.NET ):

// other includes
using Newtonsoft.Json;

Une classe avec un cookie:

public class WithCookie
{
    public Cookie MyCookie { get; set; }

    public WithCookie()
    {
        MyCookie = new Cookie("CF788DF", "A cookie value!", "/", ".test.com");
    }
}

Voici comment il sérialisation JSON:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            WithCookie wc1 = new WithCookie();
            // Expires a month from now
            wc1.MyCookie.Expires = DateTime.Now.AddMonths(1);

            string wc1json = JsonConvert.SerializeObject(new WithCookie());

            WithCookie wc2 = JsonConvert.DeserializeObject < WithCookie>(wc1json);

            string wc2json = JsonConvert.SerializeObject(wc2);

            if (wc2json == wc1json)
            {
                Console.WriteLine("HORRAY!");
            }
            else
            {
                // The strings will not be equal, because the Cookie.TimeStamp 
                // changes but the cookies are in fact the same!
                Console.WriteLine("FAIL!");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: " + e.ToString());
        }
        Console.ReadKey();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top