示例#1
0
        public async Task ExtractAsync(HttpZipEntry entry, Action <MemoryStream> resultCallback)
        {
            try
            {
                var fileDataBuffer = await this.ExtractAsync(entry);

                var resultStream = new MemoryStream(fileDataBuffer);
                resultStream.Position = 0;
                resultCallback.Invoke(resultStream);
                return;
            }
            catch (Exception) { throw; }
        }
示例#2
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; }
        }
示例#3
0
        public async Task <List <HttpZipEntry> > GetEntriesAsync()
        {
            try
            {
                // INITIALIZE
                var entryList = new List <HttpZipEntry>();
                if (await this.GetContentLengthAsync() == -1)
                {
                    return(null);
                }
                if (await this.LocateDirectoryAsync() == false)
                {
                    return(null);
                }

                // MAKE A HTTP CALL USING THE RANGE HEADER
                var rangeStart  = this.directoryData.Offset;
                var rangeFinish = this.directoryData.Offset + this.directoryData.Size;
                this.httpClient.DefaultRequestHeaders.Range = new RangeHeaderValue(rangeStart, rangeFinish);
                var byteArray = await httpClient.GetByteArrayAsync(this.httpUrl);

                // LOOP THROUGH ENTRIES
                var entriesOffset = 0;
                for (int entryIndex = 0; entryIndex < this.directoryData.Entries; entryIndex++)
                {
                    var entry = new HttpZipEntry(entryIndex);
                    // https://en.wikipedia.org/wiki/Zip_(file_format)#Local_file_header

                    entry.Signature     = BitConverter.ToInt32(byteArray, entriesOffset + 0); // 0x04034b50
                    entry.VersionMadeBy = BitConverter.ToInt16(byteArray, entriesOffset + 4);
                    entry.MinimumVersionNeededToExtract = BitConverter.ToInt16(byteArray, entriesOffset + 6);
                    entry.GeneralPurposeBitFlag         = BitConverter.ToInt16(byteArray, entriesOffset + 8);

                    entry.CompressionMethod    = BitConverter.ToInt16(byteArray, entriesOffset + 10);
                    entry.FileLastModification = BitConverter.ToInt32(byteArray, entriesOffset + 12);
                    entry.CRC32            = BitConverter.ToInt32(byteArray, entriesOffset + 16);
                    entry.CompressedSize   = BitConverter.ToInt32(byteArray, entriesOffset + 20);
                    entry.UncompressedSize = BitConverter.ToInt32(byteArray, entriesOffset + 24);

                    entry.FileNameLength    = BitConverter.ToInt16(byteArray, entriesOffset + 28); // (n)
                    entry.ExtraFieldLength  = BitConverter.ToInt16(byteArray, entriesOffset + 30); // (m)
                    entry.FileCommentLength = BitConverter.ToInt16(byteArray, entriesOffset + 32); // (k)

                    entry.DiskNumberWhereFileStarts = BitConverter.ToInt16(byteArray, entriesOffset + 34);
                    entry.InternalFileAttributes    = BitConverter.ToInt16(byteArray, entriesOffset + 36);
                    entry.ExternalFileAttributes    = BitConverter.ToInt32(byteArray, entriesOffset + 38);
                    entry.FileOffset = BitConverter.ToInt32(byteArray, entriesOffset + 42);

                    var fileNameStart  = entriesOffset + 46;
                    var fileNameBuffer = new byte[entry.FileNameLength];
                    Array.Copy(byteArray, fileNameStart, fileNameBuffer, 0, entry.FileNameLength);
                    entry.FileName = System.Text.Encoding.Default.GetString(fileNameBuffer);

                    var extraFieldStart  = fileNameStart + entry.FileNameLength;
                    var extraFieldBuffer = new byte[entry.ExtraFieldLength];
                    Array.Copy(byteArray, extraFieldStart, extraFieldBuffer, 0, entry.ExtraFieldLength);
                    entry.ExtraField = System.Text.Encoding.Default.GetString(extraFieldBuffer);

                    var fileCommentStart  = extraFieldStart + entry.ExtraFieldLength;
                    var fileCommentBuffer = new byte[entry.FileCommentLength];
                    Array.Copy(byteArray, fileCommentStart, fileCommentBuffer, 0, entry.FileCommentLength);
                    entry.FileComment = System.Text.Encoding.Default.GetString(fileCommentBuffer);

                    entryList.Add(entry);
                    entriesOffset = fileCommentStart + entry.FileCommentLength;
                }

                // RESULT
                return(entryList);
            }
            catch (Exception) { throw; }
        }