Pergunta

eu tenho um CookieContainer Extraído de uma sessão httpwebrequest/httpwebesponse nomeada Pote de biscoitos. Quero que meu aplicativo armazene cookies entre as corridas, então os cookies coletados no CookieContainer Em uma execução do programa, também será usado na próxima execução.

Eu acho que a maneira de fazer isso seria de alguma forma escrever o conteúdo de um cookieContainer no disco. Minha pergunta é:

  • Como você pode Escreva um cookieContainer para o disco? Existem funções internas para isso, ou, se não, quais são as abordagens que as pessoas adotaram? Existem classes disponíveis para simplificar isso?
  • Depois de escrever um cookieContainer para o disco, Como você o carrega de volta para uso?

ATUALIZAR: A primeira resposta sugeriu serialização do CookieContainer. No entanto, não estou muito familiarizado com como serializar e desserializar objetos tão complexos. Você poderia fornecer alguns Código de amostra? A sugestão foi utilizar SOAPFormatter.

Foi útil?

Solução

Eu não tentei, mas ele tem o atributo serializável e, portanto, pode ser serializado com a serialização binária .NET, por exemplo, o SoapFormatter.

Aqui está o trecho de código que você pediu.

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

Olhando para o MSDN, parece que o SoapFormatter agora está descontinuado no .NET 3.5 e recomenda que você use o BinaryFormatter. No passado, achei o SOAPFormatter útil, pois o arquivo é legível, o que ajuda no diagnóstico quando a desserialização falha! Esses formatados são sensíveis às mudanças de versão mesmo na versão de montagem (por isso um problema. Eu acredito que eles são projetados principalmente para persistência / remoção de curto prazo, mas podem ser bons o suficiente para você aqui.

O novo DataContractSerializer não parece funcionar com ele para que seja divulgado.

Uma alternativa seria escrever uma classe CookieContainerData para [de] serializar com o XMLSerializer e converter manualmente entre este e o CookiecOntainer.

Outras dicas

Esse problema estava me incomodando há muito tempo, nada que eu pudesse encontrar funcionou. Eu trabalhei, então colocando essas informações no mundo.

Resposta usando o 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(); 
        }
    }

É interessante ter Cookies em formato de texto. Além de poder ser usado para gravar no disco, ele pode ser usado para outros fins.

FUNCIONA PARA MIM!

Use o LoadCookiesFromFile e SaveCookiesToFile Funções para carregar e escrever os cookies no disco, respectivamente.

Ou use o GetCookies e SetCookies funciona para fazer a mesma coisa, mas manipulá -la como uma corda.

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

Outra alternativa é usar a serialização JSON (Json.net):

// other includes
using Newtonsoft.Json;

Uma aula com um biscoito:

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

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

Aqui está como serializar para 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();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top