示例#1
0
        private static async Task DownloadAndExtractAsync(string url, string dir)
        {
            await using Stream httpStream = await HttpClientInstance.GetStreamAsync(url);

            using IReader reader = ReaderFactory.Open(httpStream);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            while (reader.MoveToNextEntry())
            {
                IEntry entry = reader.Entry;
                if (entry.IsDirectory)
                {
                    continue;
                }

                string targetPath = Path.Combine(dir, entry.Key.Replace('/', '\\'));
                string targetDir  = Path.GetDirectoryName(targetPath);
                if (targetDir == null)
                {
                    throw new InvalidOperationException();
                }

                if (!Directory.Exists(targetDir))
                {
                    Directory.CreateDirectory(targetDir);
                }

                await using EntryStream stream = reader.OpenEntryStream();
                await using FileStream fs      = File.Create(targetPath);
                await stream.CopyToAsync(fs);
            }
        }
示例#2
0
        public static async Task ExtractAllAsync(IEnumerable <string> SourceItemGroup, string BaseDestPath, bool CreateFolder, ProgressChangedEventHandler ProgressHandler)
        {
            ulong TotalSize       = 0;
            ulong CurrentPosition = 0;

            List <FileSystemStorageFile> TransformList = new List <FileSystemStorageFile>();

            foreach (string FileItem in SourceItemGroup)
            {
                if (await FileSystemStorageItemBase.OpenAsync(FileItem).ConfigureAwait(false) is FileSystemStorageFile File)
                {
                    TransformList.Add(File);
                    TotalSize += File.SizeRaw;
                }
                else
                {
                    throw new FileNotFoundException("Could not found the file or path is a directory");
                }
            }

            if (TotalSize == 0)
            {
                return;
            }

            foreach (FileSystemStorageFile File in TransformList)
            {
                string DestPath = BaseDestPath;

                //如果解压到独立文件夹,则要额外创建目录
                if (CreateFolder)
                {
                    string NewFolderName = File.Name.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase)
                                                        ? File.Name.Substring(0, File.Name.Length - 7)
                                                        : (File.Name.EndsWith(".tar.bz2", StringComparison.OrdinalIgnoreCase)
                                                                        ? File.Name.Substring(0, File.Name.Length - 8)
                                                                        : Path.GetFileNameWithoutExtension(File.Name));

                    if (string.IsNullOrEmpty(NewFolderName))
                    {
                        NewFolderName = Globalization.GetString("Operate_Text_CreateFolder");
                    }

                    DestPath = await MakeSureCreateFolderHelperAsync(Path.Combine(BaseDestPath, NewFolderName));
                }

                if (File.Name.EndsWith(".gz", StringComparison.OrdinalIgnoreCase) && !File.Name.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase))
                {
                    await ExtractGZipAsync(File, DestPath, (s, e) =>
                    {
                        ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32((CurrentPosition + Convert.ToUInt64(e.ProgressPercentage / 100d * File.SizeRaw)) * 100d / TotalSize), null));
                    });

                    CurrentPosition += Convert.ToUInt64(File.SizeRaw);
                    ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32(CurrentPosition * 100d / TotalSize), null));
                }
                else if (File.Name.EndsWith(".bz2", StringComparison.OrdinalIgnoreCase) && !File.Name.EndsWith(".tar.bz2", StringComparison.OrdinalIgnoreCase))
                {
                    await ExtractBZip2Async(File, DestPath, (s, e) =>
                    {
                        ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32((CurrentPosition + Convert.ToUInt64(e.ProgressPercentage / 100d * File.SizeRaw)) * 100d / TotalSize), null));
                    });

                    CurrentPosition += Convert.ToUInt64(File.SizeRaw);
                    ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32(CurrentPosition * 100d / TotalSize), null));
                }
                else
                {
                    ReaderOptions ReadOptions = new ReaderOptions();
                    ReadOptions.ArchiveEncoding.Default = EncodingSetting;

                    using (FileStream InputStream = await File.GetFileStreamFromFileAsync(AccessMode.Read))
                        using (IReader Reader = ReaderFactory.Open(InputStream, ReadOptions))
                        {
                            Dictionary <string, string> DirectoryMap = new Dictionary <string, string>();

                            while (Reader.MoveToNextEntry())
                            {
                                if (Reader.Entry.IsDirectory)
                                {
                                    string DirectoryPath    = Path.Combine(DestPath, Reader.Entry.Key.Replace("/", @"\").TrimEnd('\\'));
                                    string NewDirectoryPath = await MakeSureCreateFolderHelperAsync(DirectoryPath);

                                    if (!DirectoryPath.Equals(NewDirectoryPath, StringComparison.OrdinalIgnoreCase))
                                    {
                                        DirectoryMap.Add(DirectoryPath, NewDirectoryPath);
                                    }
                                }
                                else
                                {
                                    string[] PathList = (Reader.Entry.Key?.Replace("/", @"\")?.Split(@"\")) ?? Array.Empty <string>();

                                    string LastFolder = DestPath;

                                    for (int i = 0; i < PathList.Length - 1; i++)
                                    {
                                        LastFolder = Path.Combine(LastFolder, PathList[i]);

                                        if (DirectoryMap.ContainsKey(LastFolder))
                                        {
                                            LastFolder = DirectoryMap[LastFolder];
                                        }

                                        string NewDirectoryPath = await MakeSureCreateFolderHelperAsync(LastFolder);

                                        if (!LastFolder.Equals(NewDirectoryPath, StringComparison.OrdinalIgnoreCase))
                                        {
                                            DirectoryMap.Add(LastFolder, NewDirectoryPath);
                                            LastFolder = NewDirectoryPath;
                                        }
                                    }

                                    string DestFileName = Path.Combine(LastFolder, PathList.LastOrDefault() ?? Path.GetFileNameWithoutExtension(File.Name));

                                    if (await FileSystemStorageItemBase.CreateAsync(DestFileName, StorageItemTypes.File, CreateOption.GenerateUniqueName).ConfigureAwait(false) is FileSystemStorageFile NewFile)
                                    {
                                        using (FileStream OutputStream = await NewFile.GetFileStreamFromFileAsync(AccessMode.Write))
                                            using (EntryStream EntryStream = Reader.OpenEntryStream())
                                            {
                                                await EntryStream.CopyToAsync(OutputStream, Reader.Entry.Size, (s, e) =>
                                                {
                                                    ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32((CurrentPosition + Convert.ToUInt64(e.ProgressPercentage / 100d * Reader.Entry.CompressedSize)) * 100d / TotalSize), null));
                                                });

                                                CurrentPosition += Convert.ToUInt64(Reader.Entry.CompressedSize);
                                                ProgressHandler?.Invoke(null, new ProgressChangedEventArgs(Convert.ToInt32(CurrentPosition * 100d / TotalSize), null));
                                            }
                                    }
                                }
                            }
                        }
                }
            }
        }