0

We are successfully getting many of the reports from the iTunes autoingest endpoint: https://reportingitc.apple.com/autoingestion.tft

However some of the reports, rather than returning the data directly in the body return a ZIP file and whenever we try to read the response we get:

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

The response headers look something like the following, indicating the zip file:

{
Content-Encoding:
Content-Disposition: attachment;filename=O_S_W_XXXXXXXX_20120805.zip
filename: O_S_W_XXXXXXXX_20120805.zip
Transfer-Encoding: chunked
Content-Type: application/a-gzip
Date: Wed, 29 Aug 2012 08:54:35 GMT
Set-Cookie: JSESSIONID=XXXXXXXXXXXXXXXX; Path=/
Server: Apache-Coyote/1.1
}

But I do not really see how to access this attachment and I think the error might be something to do with the fact that I am trying to ready both the attachment and other parts of the response in one operation whereas only part of the response is actually zipped.

The code looks something like this:

HttpWebRequest w = (HttpWebRequest)WebRequest.Create(url);
w.Method = "POST";

byte[] byteArray = Encoding.UTF8.GetBytes(postData);

w.ContentLength = byteArray.Length;

using (Stream dataStream = w.GetRequestStream())
{

dataStream.Write(byteArray, 0, byteArray.Length);

dataStream.Close();

using (WebResponse resp = w.GetResponse())
{

    using (System.IO.Compression.GZipStream s = new System.IO.Compression.GZipStream(resp.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress))
    {
    // Just trying to read one byte causes the error.
    s.ReadByte();
    }

}

Any ideas greatly appreciated.

rene
  • 41,474
  • 78
  • 114
  • 152
chrisb
  • 1,395
  • 1
  • 14
  • 35
  • Without seeing the http body, isn't the file base64 encoded? If yes, decode the base64 first to a byte stream and then dedcompress. – rene Aug 29 '12 at 09:44
  • Hi Rene - I can't figure out how to even get the body - whenever I try to read it I get an error. Do you have any suggested code I could try with the resp object? – chrisb Aug 29 '12 at 16:40

2 Answers2

0

Take a look at this question and its accepted answer.

Use Fiddler to intercept the bytes on the wire (see the Inspectors tab).

As it turns out from the API: the stream is not GZipped but Zipped.

Have a look here for a library to unzip a stream in c#

At the start of your app add to overcome http 100 responses:

ServicePointManager.Expect100Continue = true;

Using that you'll implement the unzipping as follows, just after you obtaind the WebResponse:

using (ZipInputStream s = new ZipInputStream(resp.GetResponseStream()) {

    ZipEntry theEntry;
    while ((theEntry = s.GetNextEntry()) != null) {

        Console.WriteLine(theEntry.Name);

        string directoryName = Path.GetDirectoryName(theEntry.Name);
        string fileName      = Path.GetFileName(theEntry.Name);

        // create directory
        if ( directoryName.Length > 0 ) {
            Directory.CreateDirectory(directoryName);
        }

        if (fileName != String.Empty) {
            using (FileStream streamWriter = File.Create(theEntry.Name)) {

                int size = 2048;
                byte[] data = new byte[2048];
                while (true) {
                    size = s.Read(data, 0, data.Length);
                    if (size > 0) {
                        streamWriter.Write(data, 0, size);
                    } else {
                        break;
                    }
                }
            }
        }
    }
}
Community
  • 1
  • 1
rene
  • 41,474
  • 78
  • 114
  • 152
  • Thanks for the suggestion - still no luck though - when I use code above I get this error on the s.GetNextEntry()call: **This operation is not supported.**

    Also, when I try to decode the response in Fiddler I get this error:
    ** --------------------------- utilDecodeResponse failed for Session #5 --------------------------- The HTTP response body was malformed.

    HTTP Error: The chunked content is corrupt. Cannot find Chunk-Length in expected location. Offset: 0

    Type: System.IO.InvalidDataException **
    – chrisb Aug 31 '12 at 09:39
  • Sorry - I can't see how I can format the above and after 5 minutes of trying it's locked me out! – chrisb Aug 31 '12 at 09:44
  • do this: start fiddler, use the java class as indicated in the answer of the question I referred to, to obtain a valid result, let fiddler mock that result, adapt your .net code until success. – rene Aug 31 '12 at 10:43
0

Finally figured this out!

I needed to set:

webRequest.AutomaticDecompression = DecompressionMethods.None;

Previously I had it set to try to:

w.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

And .NET was trying and failing to unzip the response before I even had a chance to read it.

I can now read the byte array and decrypt the file after it has been saved to disk.

chrisb
  • 1,395
  • 1
  • 14
  • 35