This is Xamarin's bug tracking system. For product support, please use the support links listed in your Xamarin Account.
Bug 30686 - ZipArchive ctor throws InvalidDataException for WebConnectionStream
Summary: ZipArchive ctor throws InvalidDataException for WebConnectionStream
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: Other (show other bugs)
Version: 4.0.0
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: ---
Assignee: João Matos
URL: https://gist.github.com/natemcmaster/...
Depends on:
Blocks:
 
Reported: 2015-06-02 15:10 UTC by Nate McMaster
Modified: 2016-07-04 11:17 UTC (History)
4 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Reproduction of bug (2.03 KB, application/octet-stream)
2015-06-02 15:10 UTC, Nate McMaster
Details

Description Nate McMaster 2015-06-02 15:10:19 UTC
Created attachment 11436 [details]
Reproduction of bug

The constructor for System.IO.Compression.ZipArchive(Stream) does not work with the result of HttpClient.GetStreamAsync.Result (which returns System.Net.WebConnectionStream).

Instead, it throws System.IO.InvalidDataException with the message "The contents of the stream are not in the zip archive format."
Comment 1 Marek Safar 2015-06-03 11:45:57 UTC
This is System.IO.Compression bug which requires Seek capability for zip read mode whereas .net requires CanRead only.
Comment 2 Martin Lantzsch 2015-06-15 17:15:28 UTC
Same bug here for System.Net.FtpDataStream (CanSeek=false, CanRead=true) on Linux. So I just got the mono source and compiled my app against the System.IO.Compression.dll and .mdb. The inner exception which was before "null" is now the following System.ArgumentException from the SharpCompress library:

    "Archive streams must be Readable and Seekable"

The method in SharpCompress's AbstractArchive class:

    private static Stream CheckStreams(Stream stream)
    {
        if (!stream.CanSeek || !stream.CanRead)
        {
           throw new ArgumentException("Archive streams must be Readable and Seekable");
        }
        return stream;
    }

The bug seems to sit in sharpcompress which is testing all input streams against this method. Funnily they write in their readme: "The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream)." (https://github.com/adamhathcock/sharpcompress)
Comment 3 João Matos 2015-06-15 17:50:26 UTC
I've tried to look into this bug last week.

If you remove those checks then the stream will fail when SharpCompress tries to seek to the end, to read the Zip header. 

A simple fix would be to download the whole stream first into memory and pass it for further handling but that feels like an hack.

Another solution would be try to use their ReaderFactory API which I think is the one that supports streaming but I didn't look if it would be possible to implement the whole .NET API with it.
Comment 4 Paul Morris 2016-03-18 19:28:39 UTC
I am getting this exception when opening a stream that I have fully loaded into memory. So my unit test looks like this:

Assert.True(stream.CanRead);
Assert.True(stream.CanSeek);
Assert.Equal(36085092, stream.Length);

var zip = new ZipArchive(stream);

The first three assertions work fine. The Length is correct. The final line throws the "ArgumentException: Archive streams must be Readable and Seekable". This one has me baffled.
Comment 5 João Matos 2016-03-18 22:07:09 UTC
Do you have a reproduction case I could test with?
Comment 6 Paul Morris 2016-03-19 12:47:33 UTC
Ok I will try to put together a a simple app to isolate the issue and post it here. Thank you.
Comment 7 Paul Morris 2016-03-19 23:05:38 UTC
Sorry for the trouble. I was dealing with a zip within a zip and the inner zipped folder was not being wrapped in a seekable stream on Mono. Working now. It would be nice of course if the Mono (SharpCompress) implementation behaved as .NET does, not require a seekable stream. Thanks for your prompt response by the way.
Comment 8 Martin Lantzsch 2016-03-21 19:58:33 UTC
Hello, I still have this problem and created a application for you to simply reproduce this issue: https://github.com/LinuxDoku/mono-bug-30686/blob/master/mono-bug-30686/Program.cs

This application works on my windows 10 machine with .NET Framework 4.5, but not with the latest mono version on ubuntu: "Stable 4.2.3.4/832de4b".

In the app above I faked the "CanSeek" property which is set to "false", equal to the behaviour when you are receiving the data from "FtpDataStream".
Comment 9 João Matos 2016-06-24 00:31:37 UTC
Looking into this.
Comment 10 João Matos 2016-07-02 01:10:31 UTC
https://github.com/mono/mono/pull/3234

Note You need to log in before you can comment on or make changes to this bug.