Как решить проблему отсутствия магического числа Gzip

У меня есть строка, которую я Gzip на сервере и загружаю клиенту с помощью класса WebClient. Когда я пытаюсь распаковать его, я получаю сообщение об ошибке, что Magic Number отсутствует. Я пробовал как класс GZipStream, так и методы ICSharpLib для решения этой проблемы, поэтому я в растерянности.

Сжатие / распаковка работает, если я пропущу этап загрузки через WebClient (используя DownloadData, который возвращает данные как byte []), поэтому я могу только предположить, что есть некоторая проблема с усечением или повреждением данных каким-то образом, но поскольку это сжатые данные, я не знаю, как это отладить.

Вот фрагмент кода, который кажется оскорбительным:

   byte[] response
   try {
        response = client.DownloadData(Constants.GetSetting("SyncServer"));
   } catch {
        MessageBox.Show("There was a problem synchronizing the data. Please try verify the supplied credentials or try again later.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
   }

   int rows = SQLiteAPI.ImportStatHistoryXML(CurrentUser.User, myCampus, Convert.ToBase64String(response));

public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, string xmlFile) {
            byte[] encryptedFile = Convert.FromBase64String(xmlFile);
            MemoryStream memStream = new MemoryStream(encryptedFile);
            memStream.ReadByte();
            GZipInputStream stream = new GZipInputStream(memStream);
            MemoryStream memory = new MemoryStream();
            byte[] writeData = new byte[4096];
            int size;

            while (true) {
                size = stream.Read(writeData, 0, writeData.Length);
                if (size > 0) {
                    memory.Write(writeData, 0, size);
                } else {
                    break;
                }
            }
            stream.Close();
            memory.Position = 0;
            StreamReader sr = new StreamReader(memory);
            string decompressed = sr.ReadToEnd();
            DataSet tempSet = new DataSet();
            StringReader xmlReader = new StringReader(decompressed);
            tempSet.ReadXml(xmlReader);
            DataTable statTable = tempSet.Tables["Stats"];
...more unrelated processing of the table
}

Любая помощь будет оценена. P.S. Я использую строку Base64, чтобы иметь возможность передавать туда и обратно через Интернет. На самом деле это может быть та область, в которой я ошибаюсь, поскольку раньше я не выполнял веб-запросы и ответы между настольным приложением и веб-службой.


person Jared    schedule 22.06.2009    source источник


Ответы (1)


Во-первых, я не думаю, что этот фрагмент действителен, потому что DownloadString возвращает (как и ожидалось) строку.

Я правильно понимаю, что он работает правильно, когда вы используете DownloadData, и неправильно, когда вы используете DownloadString? Это имеет смысл, потому что декодировать данные Gzip как Unicode недопустимо.

РЕДАКТИРОВАТЬ:

Хорошо, ToBase64String и FromBase64String должны быть в порядке. Но если вы можете избежать этого и передать byte [] напрямую, это было бы хорошо.

public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, byte[] compressedFile) {

Тогда вы избавитесь от первой строки функции (декодирование из base64). Обратите внимание, что мы переименовываем encryptedFile в compressedFile.

Линия:

memStream.ReadByte();

не должно быть там. Вы читаете байт и отбрасываете его. Если все так, как мы ожидали, байт равен 0x1F, это часть магического числа gzip.

Тогда, я думаю, вы используете неправильный класс gzip. Вам нужен GZipStream. Он построен как:

GZipStream stream = new GZipStream(memStream, CompressionMode.Decompress);

Затем вы используете StreamReader непосредственно для этого:

StreamReader sr = new StreamReader(stream);

Было бы полезно, если бы вы знали кодировку, но, надеюсь, значение по умолчанию будет правильным. Тогда это кажется правильным. Итак, в целом мы получаем следующее.

public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, byte[] compressedFile) {
    MemoryStream memStream = new MemoryStream(compressedFile);
    GZipStream gzStream = new GZipStream(memStream, CompressionMode.Decompress);
    StreamReader sr = new StreamReader(gzStream);
    string decompressed = sr.ReadToEnd();
    DataSet tempSet = new DataSet();
    StringReader xmlReader = new StringReader(decompressed);
    tempSet.ReadXml(xmlReader);
    DataTable statTable = tempSet.Tables["Stats"];

    //...
}
person Matthew Flaschen    schedule 22.06.2009
comment
Ты прав. Извини, что я пытался изо всех сил попытаться выяснить, смогу ли я исправить то, чего не хватало. - person Jared; 22.06.2009
comment
Спасибо. Теперь код имеет больше смысла, но вы не ответили на мой вопрос. - person Matthew Flaschen; 22.06.2009
comment
У меня есть строка в кодировке base64? Это не сработает? Как затем передать данные в формате Gzip в веб-службу и обратно? - person Jared; 22.06.2009
comment
Джаред, ты действительно не помог мне разобраться в проблеме. Вы все еще не ответили на мой вопрос. Другой - когда вы на самом деле декодируете данные gzip? Очевидно, что в вашем коротком фрагменте нет ссылки на GZipStream или ICSharpLib. У вас может быть или не быть причины использовать Base64 (возможно, нет). Я все еще пытаюсь понять, что ты делаешь. - person Matthew Flaschen; 22.06.2009
comment
Спасибо, что остались со мной в этом вопросе. Хорошо, я добавил код декомпрессии. Я был бы рад не использовать преобразования строк, но я не уверен, как загружать / скачивать данные без них (я никогда не выполнял передачи с рабочего стола на веб, всегда только с рабочего стола или просто ASP.Net, поэтому совершенно новый область для меня.) - person Jared; 22.06.2009
comment
Привет, я улучшил ImportStatHistoryXML. Надеюсь, это помогает. - person Matthew Flaschen; 23.06.2009
comment
Спасибо. Это позволило мне отладить, что настоящая проблема заключалась в том, что веб-сервис возвращал дополнительный контент, чем просто сжатые данные, так что спасибо! - person Jared; 25.06.2009
comment
@Matthew: Я собираюсь проголосовать за тебя, просто за твою настойчивость. - person Mizipzor; 06.10.2010