Подтвердить что ты не робот

С#: Написание CookieContainer на диск и загрузка обратно для использования

У меня есть CookieContainer, извлеченный из сеанса HttpWebRequest/HttpWebResponse с именем CookieJar. Я хочу, чтобы мое приложение хранило файлы cookie между прогонами, поэтому файлы cookie, собранные в CookieContainer в одном прогоне программы, также будут использоваться в следующем запуске.

Я думаю, что способ сделать это - это как-то написать содержимое CookieContainer на диск. Мой вопрос:

  • Как вы можете написать CookieContainer на диск? Существуют ли встроенные функции для этого или, если нет, какие подходы люди предпринимают? Существуют ли какие-либо классы для упрощения этого?
  • Как только вы написали CookieContainer на диск, , как вы его загрузите для использования?

ОБНОВЛЕНИЕ:. Первый ответ предложил сериализацию CookieContainer. Однако я не очень хорошо разбираюсь в том, как сериализовать и десериализовать такие сложные объекты. Не могли бы вы предоставить код ? Было предложено использовать SOAPFormatter.

4b9b3361

Ответ 1

Я не пробовал, но имеет атрибут Serializable и поэтому может быть [de] сериализован с .net-сериализацией .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 для [de] сериализации с XmlSerializer и вручную преобразовать между этим и CookieContainer.

Ответ 2

Эта проблема искала меня целую вечность, я ничего не смог найти. Я проработал, поэтому отправляю эту информацию в мир.

Ответ с использованием 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(); 
        }
    }

Ответ 3

Другой альтернативой является использование сериализации Json (Json.NET):

// other includes
using Newtonsoft.Json;

Класс с файлом cookie:

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

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

Вот как сериализовать его в 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();
    }
}