Как да решим Gzip Magic Number Missing

Имам низ, който архивирам в Gzip на сървъра и го изтегля на клиент с помощта на класа WebClient. Когато се опитам да го декомпресирам, получавам съобщение за грешка, че магическото число липсва. Опитах както класа 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