Example #1
0
        public async Task <byte[]> ExtractAsync(HttpZipEntry entry)
        {
            try
            {
                // MAKE A HTTP CALL USING THE RANGE HEADER
                var fileHeaderLength = 30 + entry.FileNameLength + entry.ExtraFieldLength;
                var rangeStart       = entry.FileOffset;
                var rangeFinish      = entry.FileOffset + fileHeaderLength + entry.CompressedSize;
                this.httpClient.DefaultRequestHeaders.Range = new RangeHeaderValue(rangeStart, rangeFinish);
                var byteArray = await httpClient.GetByteArrayAsync(this.httpUrl);

                // LOCATE DATA BOUNDS
                // https://en.wikipedia.org/wiki/Zip_(file_format)#Local_file_header
                var fileSignature     = BitConverter.ToInt32(byteArray, 0);
                var bitFlag           = BitConverter.ToInt16(byteArray, 6);
                var compressionMethod = BitConverter.ToInt16(byteArray, 8);
                var crc              = BitConverter.ToInt32(byteArray, 14);
                var compressedSize   = BitConverter.ToInt32(byteArray, 18);
                var uncompressedSize = BitConverter.ToInt32(byteArray, 22);
                var fileNameLength   = BitConverter.ToInt16(byteArray, 26); // (n)
                var extraFieldLength = BitConverter.ToInt16(byteArray, 28); // (m)
                var fileDataOffset   = 30 + fileNameLength + extraFieldLength;
                var fileDataSize     = entry.CompressedSize;

                // EXTRACT DATA BUFFER
                var fileDataBuffer = new byte[fileDataSize];
                Array.Copy(byteArray, fileDataOffset, fileDataBuffer, 0, fileDataSize);
                Array.Clear(byteArray, 0, byteArray.Length);
                byteArray = null;

                /* STORED */
                if (entry.CompressionMethod == 0)
                {
                    return(fileDataBuffer);
                }

                /* DEFLATED */
                if (entry.CompressionMethod == 8)
                {
                    var deflatedArray = new byte[entry.UncompressedSize];
                    using (var compressedStream = new MemoryStream(fileDataBuffer))
                    {
                        using (var deflateStream = new System.IO.Compression.DeflateStream(compressedStream, CompressionMode.Decompress))
                        {
                            await deflateStream.ReadAsync(deflatedArray, 0, deflatedArray.Length);
                        }

                        /*
                         * using (var deflatedStream = new MemoryStream())
                         * {
                         * var deflater = new System.IO.Compression.DeflateStream(compressedStream, CompressionMode.Decompress, true);
                         *
                         * byte[] buffer = new byte[1024];
                         * var bytesPending = entry.UncompressedSize;
                         * while (bytesPending > 0)
                         * {
                         *    var bytesRead = deflater.Read(buffer, 0, (int)Math.Min(bytesPending, buffer.Length));
                         *    deflatedStream.Write(buffer, 0, bytesRead);
                         *    bytesPending -= (uint)bytesRead;
                         *    if (bytesRead == 0) { break; }
                         * }
                         *
                         * deflatedArray = deflatedStream.ToArray();
                         * }
                         */
                    }
                    return(deflatedArray);
                }

                // NOT SUPPORTED COMPRESSION METHOD
                throw new NotSupportedException($"The compression method [{entry.CompressionMethod}] is not supported");
            }
            catch (Exception) { throw; }
        }