C#:将 CookieContainer 写入磁盘并重新加载以供使用

发布于 2024-08-12 05:31:00 字数 618 浏览 4 评论 0原文

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

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

  • 如何将 CookieContainer 写入磁盘?是否有内置函数可以实现此目的?如果没有,人们采取的方法是什么?是否有任何类可用于简化此操作?
  • 将 CookieContainer 写入磁盘后,如何将其重新加载以供使用

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

I have a CookieContainer extracted from a HttpWebRequest/HttpWebResponse session named CookieJar. I want my application to store cookies between runs, so cookies collected in the CookieContainer on one run of the program will be used the next run, too.

I think the way to do this would be to somehow write the contents of a CookieContainer to disk. My question is:

  • How can you write a CookieContainer to the disk? Are there built-in functions for this, or, if not, what are the approaches people have taken? Are there any classes available for simplifying this?
  • Once you've written a CookieContainer to the disk, how do you load it back in for use?

UPDATE: The first answer has suggested serialization of the CookieContainer. However, I am not very familiar with how to serialize and deserialize such complex objects. Could you provide some sample code? The suggestion was to utilise SOAPFormatter.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最终幸福 2024-08-19 05:31:00

这个问题困扰了我很多年,我找不到任何解决办法。我解决了这个问题,所以将这些信息公诸于世。

使用 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(); 
        }
    }

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(); 
        }
    }
森末i 2024-08-19 05:31:00

我还没有尝试过,但它具有可序列化属性,因此可以使用 .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 很有用,因为该文件是可读的,这有助于在反序列化失败时进行诊断!即使在程序集版本中,这些格式化程序对版本更改也很敏感(因此,如果您使用框架的一个版本升级框架进行反序列化,那么它可能不会反序列化,不确定),但是如果这变成了,可以使用 Binder 属性解决此问题一个问题。我相信它们主要是为短期持久性/远程处理而设计的,但它们可能对您来说已经足够好了。

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

另一种方法是编写一个 CookieContainerData 类,以使用 XmlSerializer 进行反序列化,并在该类与 CookieContainer 之间手动进行转换。

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.

老子叫无熙 2024-08-19 05:31:00

由于使用 IFormatter 类进行序列化已被弃用,以前的所有答案都已过时 https://aka.ms/所以

现在正确的方法是使用支持 IEnumerable的其他方法对其进行序列化。

的示例

这是使用 System.Text.Json序列化

await using var fs = File.OpenWrite("cookies.json");
// Beware: GetAllCookies is available starting with .NET 6
JsonSerializer.Serialize(fs, cookieContainer.GetAllCookies());

反序列化

var cookieContainer = new CookieContainer();
await using var fs = File.OpenRead("cookies.json");
var cookieCollection = JsonSerializer.Deserialize<CookieCollection>(fs);
cookieContainer.Add(cookieCollection);

All of the previous answers are outdated since serializing using IFormatter classes was deprecated https://aka.ms/binaryformatter

So the correct method now is serializing it using something else that supports IEnumerable<T>.

Here's an example using System.Text.Json

Serialize

await using var fs = File.OpenWrite("cookies.json");
// Beware: GetAllCookies is available starting with .NET 6
JsonSerializer.Serialize(fs, cookieContainer.GetAllCookies());

Deserialize

var cookieContainer = new CookieContainer();
await using var fs = File.OpenRead("cookies.json");
var cookieCollection = JsonSerializer.Deserialize<CookieCollection>(fs);
cookieContainer.Add(cookieCollection);
燃情 2024-08-19 05:31:00

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

适合我!

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

或者使用 GetCookies 和 SetCookies 函数执行相同的操作,但将其作为字符串进行操作。

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

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.
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文