C#: Writing a CookieContainer to Disk and Loading Back In For Use

六眼飞鱼酱① 提交于 2019-11-28 17:15:07

I Haven't tried it but it has the attribute Serializable and so can be [de]serialized with .net binary serialization, e.g. SoapFormatter.

Here is the code snippet you asked for.

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

Looking at msdn it seems SoapFormatter is now deprecated in .net 3.5 and it recommends you use Binaryformatter. In the past I have found SoapFormatter useful as the file is readable which helps with diagnosis when deserialization fails! These formatters are sensitive to version changes even in the assembly version (so if you deserialize with one version of the framework upgrade the framework, then it might not deserialize, not sure), but there are ways around this with the Binder property if this becomes a problem. I believe they are primarily designed for short term persistance / remoting, but they might be good enough for you here.

The new DataContractSerializer does not seem to work with it so that is out.

An alternative would be to write a CookieContainerData class to [de]serialize with XmlSerializer and manually convert between this and CookieContainer.

This problem was bugging me for ages, nothing I could find worked. I worked it out, so putting that information out into the world.

Answer using 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(); 
        }
    }

It is interesting to have cookies in text format. Besides being able to be used to write to disk, it can be used for other purposes.

WORKS FOR ME!

Use the LoadCookiesFromFile and SaveCookiesToFile functions to load and write the cookies to the disk respectively.

Or use the GetCookies and SetCookies functions to do the same thing, but to manipulate it as a string.

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.
    }
}

Another alternative is to use Json serialization (Json.NET):

// other includes
using Newtonsoft.Json;

A class with a cookie:

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

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

Here is how to serialize it to 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();
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!