3
votes

This is probably a very localized question not useful for the rest of the community but hopefully someone can help me.

What I know

I have a base64 encoded ZIP, in a string, inside an XML element.

The file looks like this:

<Document>
   <Content vesion="1"><!-- BASE64 STRING ---></Content>
</Document>

What I want to do

Decode the string, and then unzip it.

What I've tries so far (and failed)

  • Decoded the base64 string and put it in a file with a zip extension

    public string DecodeFrom64(string encodedData)
    {
    
        byte[] encodedDataAsBytes
    
            = System.Convert.FromBase64String(encodedData);
    
        string returnValue =
    
           System.Text.Encoding.Unicode.GetString(encodedDataAsBytes);
    
        return returnValue;
    
    }
    
  • Tried to unzip the string with the function:

    public static string DecompressString(string compressedText)
    {
        byte[] gZipBuffer = Convert.FromBase64String(compressedText);
        using (var memoryStream = new MemoryStream())
        {
            int dataLength = BitConverter.ToInt32(gZipBuffer, 0);
            memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4);
    
            var buffer = new byte[dataLength];
    
            memoryStream.Position = 0;
            using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                gZipStream.Read(buffer, 0, buffer.Length);
            }
    
            return Encoding.UTF8.GetString(buffer);
        }
    }
    

Got the error:

The magic number in GZip header is not correct. Make sure you are passing in a GZip stream...

  • Tried to decompress the string with the function:

    public static string UnZipStr(string compressedText)
    {
        byte[] input = Convert.FromBase64String(compressedText);
        using (MemoryStream inputStream = new MemoryStream(input))
        {
            using (DeflateStream gzip =
              new DeflateStream(inputStream, CompressionMode.Decompress))
            {
                using (StreamReader reader =
                  new StreamReader(gzip, System.Text.Encoding.UTF8))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
    

Got the error:

Block length does not match with its complement...

I sent a mail to the guys that are sending this XML data to my customer, but the problem is that they are very slow to respond (3-4 weeks).

So I am hoping someone can point me in the right direction.

I can not append files to the question, so if someone wants have a look at it I can send a mail or something?

1
Did you try rewriting the third way with GZipStream?Sergey Kalinichenko
@JoachimIsaksson: I did look at the UnZipStr functionJester
Could you show the first few bytes of the file the first option writes to disk? Preferably in hex.Joachim Isaksson
This is all wrong. The result of base64 decoding is not a string, and you shouldn't pretend that it is. Also, you're now decoding from base64 twice.harold
Even though it works, I'm not at all convinced that it's actually correct. The data is supposed to be a base64-encoded ZIP-file, right? Not a base64-encoded "ZIP-file that is plain text", because that doesn't exist. Just save the bytes as bytes, which is what they are.harold

1 Answers

5
votes

As Harold already pointed out in the comments, this is all wrong. In your last comment (Jester) you clarified that the zip file was first converted to a string, and then that string got converted to a base64 string. As this absolutely makes no sense (why should you do that), I imagine that you got something wrong there and really mean that the file got converted to a base64 string. This is best practice for email for example, and I've recently been doing that to transfer files via XML in XMPP. My guess would be that...

byte[] file = System.Convert.FromBase64String(encodedData);
File.WriteAllBytes(directoryToWriteTo+filename+".zip", file);

... creates the file you're looking for. byte[] here already IS a zip file. As zip files can be messy to deal with (as you didn't really say what's in there), I would recommend saving these bytes to a file and try to open it with a zip-software like WinRar. If this worked and you can get the file contents out of the zip file, you could ask another question how to the the contents. I would also recommend using SharpZipLib.dll, because it's really the only solution I got working in reasonable time so far.