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); } }
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)); } } } } } } } }