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; } }
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; } }
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; } }