protected override void Dispose(bool disposing) { if (this._disposed) { return; } if (disposing && !this._exceptionPending) { this._FinishCurrentEntry(); this._directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(this._outputStream, this._entriesWritten.Values, 1u, this._zip64, this.Comment, new ZipContainer(this)); CountingStream countingStream = this._outputStream as CountingStream; Stream stream; if (countingStream != null) { stream = countingStream.WrappedStream; countingStream.Dispose(); } else { stream = this._outputStream; } if (!this._leaveUnderlyingStreamOpen) { stream.Dispose(); } this._outputStream = null; } this._disposed = true; }
private void _FinishCurrentEntry() { if (this._currentEntry != null) { if (this._needToWriteEntryHeader) { this._InitiateCurrentEntry(true); } this._currentEntry.FinishOutputStream(this._outputStream, this._outputCounter, this._encryptor, this._deflater, this._entryOutputStream); this._currentEntry.PostProcessOutput(this._outputStream); if (this._currentEntry.OutputUsedZip64.HasValue) { this._anyEntriesUsedZip64 |= this._currentEntry.OutputUsedZip64.Value; } this._outputCounter = null; this._encryptor = (this._deflater = null); this._entryOutputStream = null; } }
/// <summary> /// Save the zip archive to the specified stream. /// </summary> /// /// <remarks> /// <para> /// The <c>ZipFile</c> instance is written to storage - typically a zip file /// in a filesystem, but using this overload, the storage can be anything /// accessible via a writable stream - only when the caller calls <c>Save</c>. /// </para> /// /// <para> /// Use this method to save the zip content to a stream directly. A common /// scenario is an ASP.NET application that dynamically generates a zip file /// and allows the browser to download it. The application can call /// <c>Save(Response.OutputStream)</c> to write a zipfile directly to the /// output stream, without creating a zip file on the disk on the ASP.NET /// server. /// </para> /// /// <para> /// Be careful when saving a file to a non-seekable stream, including /// <c>Response.OutputStream</c>. When DotNetZip writes to a non-seekable /// stream, the zip archive is formatted in such a way that may not be /// compatible with all zip tools on all platforms. It's a perfectly legal /// and compliant zip file, but some people have reported problems opening /// files produced this way using the Mac OS archive utility. /// </para> /// /// </remarks> /// /// <example> /// /// This example saves the zipfile content into a MemoryStream, and /// then gets the array of bytes from that MemoryStream. /// /// <code lang="C#"> /// using (var zip = new Pathfinding.Ionic.Zip.ZipFile()) /// { /// zip.CompressionLevel= Pathfinding.Ionic.Zlib.CompressionLevel.BestCompression; /// zip.Password = "******"; /// zip.Encryption = EncryptionAlgorithm.WinZipAes128; /// zip.AddFile(sourceFileName); /// MemoryStream output = new MemoryStream(); /// zip.Save(output); /// /// byte[] zipbytes = output.ToArray(); /// } /// </code> /// </example> /// /// <example> /// <para> /// This example shows a pitfall you should avoid. DO NOT read /// from a stream, then try to save to the same stream. DO /// NOT DO THIS: /// </para> /// /// <code lang="C#"> /// using (var fs = new FileSteeam(filename, FileMode.Open)) /// { /// using (var zip = Pathfinding.Ionic.Zip.ZipFile.Read(inputStream)) /// { /// zip.AddEntry("Name1.txt", "this is the content"); /// zip.Save(inputStream); // NO NO NO!! /// } /// } /// </code> /// /// <para> /// Better like this: /// </para> /// /// <code lang="C#"> /// using (var zip = Pathfinding.Ionic.Zip.ZipFile.Read(filename)) /// { /// zip.AddEntry("Name1.txt", "this is the content"); /// zip.Save(); // YES! /// } /// </code> /// /// </example> /// /// <param name="outputStream"> /// The <c>System.IO.Stream</c> to write to. It must be /// writable. If you created the ZipFile instanct by calling /// ZipFile.Read(), this stream must not be the same stream /// you passed to ZipFile.Read(). /// </param> public void Save(Stream outputStream) { if (outputStream == null) { throw new ArgumentNullException("outputStream"); } if (!outputStream.CanWrite) { throw new ArgumentException("Must be a writable stream.", "outputStream"); } // if we had a filename to save to, we are now obliterating it. _name = null; _writestream = new CountingStream(outputStream); _contentsChanged = true; _fileAlreadyExists = false; Save(); }
public static bool WriteCentralDirectoryStructure(Stream s, ICollection <ZipEntry> entries, uint numSegments, Zip64Option zip64, string comment, ZipContainer container) { ZipSegmentedStream zipSegmentedStream = s as ZipSegmentedStream; if (zipSegmentedStream != null) { zipSegmentedStream.ContiguousWrite = true; } long num = 0L; using (MemoryStream memoryStream = new MemoryStream()) { foreach (ZipEntry current in entries) { if (current.IncludedInMostRecentSave) { current.WriteCentralDirectoryEntry(memoryStream); } } byte[] array = memoryStream.ToArray(); s.Write(array, 0, array.Length); num = (long)array.Length; } CountingStream countingStream = s as CountingStream; long num2 = (countingStream == null) ? s.Position : countingStream.ComputedPosition; long num3 = num2 - num; uint num4 = (zipSegmentedStream == null) ? 0u : zipSegmentedStream.CurrentSegment; long num5 = num2 - num3; int num6 = ZipOutput.CountEntries(entries); bool flag = zip64 == Zip64Option.Always || num6 >= 65535 || num5 > (long)((ulong)-1) || num3 > (long)((ulong)-1); byte[] array3; if (flag) { if (zip64 == Zip64Option.Default) { StackFrame stackFrame = new StackFrame(1); if (stackFrame.GetMethod().DeclaringType == typeof(ZipFile)) { throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property."); } throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property."); } else { byte[] array2 = ZipOutput.GenZip64EndOfCentralDirectory(num3, num2, num6, numSegments); array3 = ZipOutput.GenCentralDirectoryFooter(num3, num2, zip64, num6, comment, container); if (num4 != 0u) { uint value = zipSegmentedStream.ComputeSegment(array2.Length + array3.Length); int num7 = 16; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); num7 += 4; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); num7 = 60; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); num7 += 4; num7 += 8; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); } s.Write(array2, 0, array2.Length); } } else { array3 = ZipOutput.GenCentralDirectoryFooter(num3, num2, zip64, num6, comment, container); } if (num4 != 0u) { ushort value2 = (ushort)zipSegmentedStream.ComputeSegment(array3.Length); int num8 = 4; Array.Copy(BitConverter.GetBytes(value2), 0, array3, num8, 2); num8 += 2; Array.Copy(BitConverter.GetBytes(value2), 0, array3, num8, 2); num8 += 2; } s.Write(array3, 0, array3.Length); if (zipSegmentedStream != null) { zipSegmentedStream.ContiguousWrite = false; } return(flag); }