Ionic.Zip.ZipFile.Save C# (CSharp) Method

Save() public method

Saves the Zip archive to a file, specified by the Name property of the ZipFile.

The ZipFile instance is written to storage, typically a zip file in a filesystem, only when the caller calls Save. In the typical case, the Save operation writes the zip content to a temporary file, and then renames the temporary file to the desired name. If necessary, this method will delete a pre-existing file before the rename.

The ZipFile.Name property is specified either explicitly, or implicitly using one of the parameterized ZipFile constructors. For COM Automation clients, the Name property must be set explicitly, because COM Automation clients cannot call parameterized constructors.

When using a filesystem file for the Zip output, it is possible to call Save multiple times on the ZipFile instance. With each call the zip content is re-written to the same output file.

Data for entries that have been added to the ZipFile instance is written to the output when the Save method is called. This means that the input streams for those entries must be available at the time the application calls Save. If, for example, the application adds entries with AddEntry using a dynamically-allocated MemoryStream, the memory stream must not have been disposed before the call to Save. See the property for more discussion of the availability requirements of the input stream for an entry, and an approach for providing just-in-time stream lifecycle management.

/// Thrown if you haven't specified a location or stream for saving the zip, /// either in the constructor or by setting the Name property, or if you try /// to save a regular zip archive to a filename with a .exe extension. /// /// Thrown if is non-zero, and the number /// of segments that would be generated for the spanned zip file during the /// save operation exceeds 99. If this happens, you need to increase the /// segment size. ///
public Save ( ) : void
return void
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                    throw new BadStateException("You haven't specified where to save the zip.");

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                    throw new BadStateException("You specified an EXE for a plain zip file.");

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose) StatusMessageTextWriter.WriteLine("No save is necessary....");
                    return;
                }

                Reset(true);

                if (Verbose) StatusMessageTextWriter.WriteLine("saving....");

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection<ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                        break;

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                        break;

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                }



                if (_saveOperationCanceled)
                    return;

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss!=null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                    (WriteStream,
                     c,
                     _numberOfSegmentsForMostRecentSave,
                     _zip64,
                     Comment,
                     new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64 = new Nullable<bool>(thisSaveUsedZip64);

                if (_fileAlreadyExists && this._readstream != null)
                {
                    // This means we opened and read a zip file.
                    // If we are now saving, we need to close the orig file, first.
                    this._readstream.Close();
                    this._readstream = null;
                }
                // the archiveStream for each entry needs to be null
                foreach (var e in c)
                {
                    var zss1 = e._archiveStream as ZipSegmentedStream;
                    if (zss1 != null)
#if NETCF
                        zss1.Close();
#else
                        zss1.Dispose();
#endif
                    e._archiveStream = null;
                }

                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName!=null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
#if NETCF
                    WriteStream.Close();
#else
                    WriteStream.Dispose();
#endif

                    if (_saveOperationCanceled)
                        return;

                    string tmpName = null;
                    if (File.Exists(_name))
                    {
                        // the steps:
                        //
                        // 1. Delete tmpName
                        // 2. move existing zip to tmpName
                        // 3. rename (File.Move) working file to name of existing zip
                        // 4. delete tmpName
                        //
                        // This series of steps avoids the exception,
                        // System.IO.IOException:
                        //   "Cannot create a file when that file already exists."
                        //
                        // Cannot just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // But, when doing the delete, Windows allows a process to
                        // delete the file, even though it is held open by, say, a
                        // virus scanner. It gets internally marked as "delete
                        // pending". The file does not actually get removed from the
                        // file system, it is still there after the File.Delete
                        // call.
                        //
                        // Therefore, we need to move the existing zip, which may be
                        // held open, to some other name. Then rename our working
                        // file to the desired name, then delete (possibly delete
                        // pending) the "other name".
                        //
                        // Ideally this would be transactional. It's possible that the
                        // delete succeeds and the move fails. Lacking transactions, if
                        // this kind of failure happens, we're hosed, and this logic will
                        // throw on the next File.Move().
                        //
                        //File.Delete(_name);
                        // workitem 10447
#if NETCF || SILVERLIGHT
                        tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8,0) + ".tmp";
#else
                        tmpName = _name + "." + Path.GetRandomFileName();
#endif
                        if (File.Exists(tmpName))
                            DeleteFileWithRetry(tmpName);
                        File.Move(_name, tmpName);
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName,
                              _name);

                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    if (tmpName != null)
                    {
                        try
                        {
                            // not critical
                            if (File.Exists(tmpName))
                                File.Delete(tmpName);
                        }
                        catch
                        {
                            // don't care about exceptions here.
                        }

                    }
                    _fileAlreadyExists = true;
                }
                _readName = _name;

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }

Same methods

ZipFile::Save ( Stream outputStream ) : void
ZipFile::Save ( String fileName ) : void

Usage Example

Beispiel #1
0
		public string CreateArchiveWithFiles(IEnumerable<Guid> files, string serverDirectoryPath, string userName, string archiveName)
		{
			string path = string.Format("{0}{1}\\{2}\\", serverDirectoryPath, _temp, userName);
			if (Directory.Exists(path))
			{
				Directory.Delete(path, true);
			}
			Directory.CreateDirectory(path);
			var fullPath = string.Format("{0}{1}", path, archiveName);

			using (var archive = new ZipFile(fullPath))
			{
				foreach (var file in files)
				{
					var document = _documentService.GetDocumentInfo(file);
					var documentBytes = _documentService.GetDocument(file);
					archive.AddEntry(document.Name, documentBytes);
					archive.Save();
				}

				archive.Save();
			}

			return fullPath;
		}
All Usage Examples Of Ionic.Zip.ZipFile::Save