示例#1
0
        /// <summary>
        /// 执行ZIP解压功能
        /// </summary>
        /// <param name="File">ZIP文件</param>
        /// <returns>无</returns>
        public static async Task ExtractZipAsync(FileSystemStorageFolder NewFolder, FileSystemStorageFile File, ProgressChangedEventHandler ProgressHandler = null)
        {
            using (FileStream BaseStream = await File.GetFileStreamFromFileAsync(AccessMode.Exclusive).ConfigureAwait(false))
                using (ZipInputStream InputZipStream = new ZipInputStream(BaseStream))
                {
                    BaseStream.Seek(0, SeekOrigin.Begin);

                    InputZipStream.IsStreamOwner = false;

                    long CurrentPosition = 0;

                    while (InputZipStream.GetNextEntry() is ZipEntry Entry)
                    {
                        if (!InputZipStream.CanDecompressEntry || Entry.IsCrypted)
                        {
                            throw new NotImplementedException();
                        }

                        if (Entry.Name.Contains("/"))
                        {
                            string[] SplitFolderPath = Entry.Name.Split('/', StringSplitOptions.RemoveEmptyEntries);

                            string TempFolderPath = NewFolder.Path;

                            for (int i = 0; i < SplitFolderPath.Length - 1; i++)
                            {
                                if (await FileSystemStorageItemBase.CreateAsync(Path.Combine(TempFolderPath, SplitFolderPath[i]), StorageItemTypes.Folder, CreateOption.OpenIfExist).ConfigureAwait(false) is FileSystemStorageFolder NextFolder)
                                {
                                    TempFolderPath = NextFolder.Path;
                                }
                                else
                                {
                                    throw new UnauthorizedAccessException("Could not create directory");
                                }
                            }

                            if (Entry.Name.Last() == '/')
                            {
                                if (await FileSystemStorageItemBase.CreateAsync(Path.Combine(TempFolderPath, SplitFolderPath.Last()), StorageItemTypes.Folder, CreateOption.OpenIfExist).ConfigureAwait(false) == null)
                                {
                                    throw new UnauthorizedAccessException("Could not create directory");
                                }
                            }
                            else
                            {
                                if (await FileSystemStorageItemBase.CreateAsync(Path.Combine(TempFolderPath, SplitFolderPath.Last()), StorageItemTypes.File, CreateOption.GenerateUniqueName).ConfigureAwait(false) is FileSystemStorageFile NewFile)
                                {
                                    using (FileStream NewFileStream = await NewFile.GetFileStreamFromFileAsync(AccessMode.Write).ConfigureAwait(false))
                                    {
                                        //For some files in Zip, CompressedSize or Size might less than zero, then we could not get progress by reading ZipInputStream.Length
                                        if (Entry.CompressedSize > 0 && Entry.Size > 0)
                                        {
                                            await InputZipStream.CopyToAsync(NewFileStream, (s, e) =>
                                            {
                                                ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32((CurrentPosition + Convert.ToInt64(e.ProgressPercentage / 100d * Entry.CompressedSize)) * 100d / BaseStream.Length), null));
                                            }).ConfigureAwait(false);
                                        }
                                        else
                                        {
                                            await InputZipStream.CopyToAsync(NewFileStream).ConfigureAwait(false);
                                        }
                                    }
                                }
                                else
                                {
                                    throw new UnauthorizedAccessException();
                                }
                            }
                        }
                        else
                        {
                            if (await FileSystemStorageItemBase.CreateAsync(Path.Combine(NewFolder.Path, Entry.Name), StorageItemTypes.File, CreateOption.GenerateUniqueName).ConfigureAwait(false) is FileSystemStorageFile NewFile)
                            {
                                using (FileStream NewFileStream = await NewFile.GetFileStreamFromFileAsync(AccessMode.Write).ConfigureAwait(false))
                                {
                                    //For some files in Zip, CompressedSize or Size might less than zero, then we could not get progress by reading ZipInputStream.Length
                                    if (Entry.CompressedSize > 0 && Entry.Size > 0)
                                    {
                                        await InputZipStream.CopyToAsync(NewFileStream, (s, e) =>
                                        {
                                            ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32((CurrentPosition + Convert.ToInt64(e.ProgressPercentage / 100d * Entry.CompressedSize)) * 100d / BaseStream.Length), null));
                                        }).ConfigureAwait(true);
                                    }
                                    else
                                    {
                                        await InputZipStream.CopyToAsync(NewFileStream).ConfigureAwait(false);
                                    }
                                }
                            }
                            else
                            {
                                throw new UnauthorizedAccessException();
                            }
                        }

                        ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32((CurrentPosition = BaseStream.Position) * 100d / BaseStream.Length), null));
                    }
                }
        }