33

CookieContainer从名为CookieJar的 HttpWebRequest/HttpWebResponse 会话中提取了一个。我希望我的应用程序在运行之间存储 cookie,因此在CookieContainer程序的一次运行中收集的 cookie 也将在下一次运行中使用。

我认为这样做的方法是以某种方式将 CookieContainer 的内容写入磁盘。我的问题是:

  • 如何将 CookieContainer 写入磁盘?是否有内置功能,或者,如果没有,人们采取了哪些方法?是否有任何类可用于简化此操作?
  • 将 CookieContainer 写入磁盘后,如何将其重新加载以供使用

更新:第一个答案建议. CookieContainer但是,我对如何序列化和反序列化如此复杂的对象不是很熟悉。你能提供一些示例代码吗?建议是利用SOAPFormatter.

4

3 回答 3

39

这个问题困扰了我很长时间,我找不到任何工作。我解决了这个问题,所以把这些信息公之于众。

使用 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(); 
        }
    }
于 2012-01-15T06:22:26.667 回答
22

我还没有尝试过,但它具有 Serializable 属性,因此可以使用 .net 二进制序列化来 [反] 序列化,例如 SoapFormatter。

这是您要求的代码片段。

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

查看 msdn 似乎 SoapFormatter 现在在 .net 3.5 中已弃用,它建议您使用 Binaryformatter。在过去,我发现 SoapFormatter 很有用,因为该文件是可读的,这有助于在反序列化失败时进行诊断!这些格式化程序即使在程序集版本中也对版本更改很敏感(因此,如果您使用框架的一个版本进行反序列化,升级框架,那么它可能不会反序列化,不确定),但是如果这变成一个问题。我相信它们主要是为短期持久性/远程处理而设计的,但在这里它们可能对你来说已经足够好了。

新的 DataContractSerializer 似乎无法使用它,所以它已经过时了。

另一种方法是编写一个 CookieContainerData 类以使用 XmlSerializer [反]序列化并在此和 CookieContainer 之间手动转换。

于 2009-11-22T00:01:34.440 回答
6

拥有文本格式的 cookie很有趣。除了能够用于写入磁盘之外,它还可以用于其他目的。

为我工作!

使用LoadCookiesFromFileSaveCookiesToFile函数分别加载和写入 cookie 到磁盘。

或者使用GetCookiesandSetCookies函数来做同样的事情,但是把它当作一个字符串来操作。

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.
    }
}
于 2019-03-18T00:19:16.480 回答