Exemplo n.º 1
0
        public void Pack(
            IPackStreamContext streamContext,
            IEnumerable <string> files,
            long maxArchiveSize)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            if (files == null)
            {
                throw new ArgumentNullException("files");
            }

            lock (this) {
                try {
                    context = streamContext;

                    ResetProgressData();

                    CreateFci(maxArchiveSize);

                    foreach (string file in files)
                    {
                        FileAttributes attributes;
                        DateTime       lastWriteTime;
                        Stream         fileStream = context.OpenFileReadStream(
                            file,
                            out attributes,
                            out lastWriteTime);
                        if (fileStream != null)
                        {
                            totalFileBytes += fileStream.Length;
                            totalFiles++;
                            context.CloseFileReadStream(file, fileStream);
                        }
                    }

                    long uncompressedBytesInFolder = 0;
                    currentFileNumber = -1;

                    foreach (string file in files)
                    {
                        FileAttributes attributes;
                        DateTime       lastWriteTime;
                        Stream         fileStream = context.OpenFileReadStream(
                            file, out attributes, out lastWriteTime);
                        if (fileStream == null)
                        {
                            continue;
                        }

                        if (fileStream.Length >= NativeMethods.FCI.MAX_FOLDER)
                        {
                            throw new NotSupportedException(String.Format(
                                                                CultureInfo.InvariantCulture,
                                                                "File {0} exceeds maximum file size " +
                                                                "for cabinet format.",
                                                                file));
                        }

                        if (uncompressedBytesInFolder > 0)
                        {
                            // Automatically create a new folder if this file
                            // won't fit in the current folder.
                            bool nextFolder = uncompressedBytesInFolder
                                              + fileStream.Length >= NativeMethods.FCI.MAX_FOLDER;

                            // Otherwise ask the client if it wants to
                            // move to the next folder.
                            if (!nextFolder)
                            {
                                object nextFolderOption = streamContext.GetOption(
                                    "nextFolder",
                                    new object[] { file, currentFolderNumber });
                                nextFolder = Convert.ToBoolean(
                                    nextFolderOption, CultureInfo.InvariantCulture);
                            }

                            if (nextFolder)
                            {
                                FlushFolder();
                                uncompressedBytesInFolder = 0;
                            }
                        }

                        if (currentFolderTotalBytes > 0)
                        {
                            currentFolderTotalBytes = 0;
                            currentFolderNumber++;
                            uncompressedBytesInFolder = 0;
                        }

                        currentFileName = file;
                        currentFileNumber++;

                        currentFileTotalBytes     = fileStream.Length;
                        currentFileBytesProcessed = 0;
                        OnProgress(ArchiveProgressType.StartFile);

                        uncompressedBytesInFolder += fileStream.Length;

                        AddFile(
                            file,
                            fileStream,
                            attributes,
                            lastWriteTime,
                            false,
                            CompressionLevel);
                    }

                    FlushFolder();
                    FlushCabinet();
                } finally {
                    if (CabStream != null)
                    {
                        context.CloseArchiveWriteStream(
                            currentArchiveNumber,
                            currentArchiveName,
                            CabStream);
                        CabStream = null;
                    }

                    if (FileStream != null)
                    {
                        context.CloseFileReadStream(
                            currentFileName, FileStream);
                        FileStream = null;
                    }

                    context = null;

                    if (fciHandle != null)
                    {
                        fciHandle.Dispose();
                        fciHandle = null;
                    }
                }
            }
        }