Skip to content

Commit 18ee122

Browse files
committed
feat(ZipArchiveService): add ArchiveDirectoryAsync method
1 parent c045592 commit 18ee122

2 files changed

Lines changed: 50 additions & 131 deletions

File tree

src/BootstrapBlazor/Services/DefaultZipArchiveService.cs

Lines changed: 24 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -13,63 +13,62 @@ class DefaultZipArchiveService : IZipArchiveService
1313
/// <summary>
1414
/// <inheritdoc/>
1515
/// </summary>
16-
/// <param name="files">要归档的文件集合</param>
17-
/// <param name="options">归档配置</param>
18-
/// <returns>归档数据流</returns>
19-
public async Task<Stream> ArchiveAsync(IEnumerable<string> files, ArchiveOptions? options = null)
16+
public async Task<Stream> ArchiveAsync(IEnumerable<ArchiveEntry> entries, ArchiveOptions? options = null)
2017
{
2118
var stream = new MemoryStream();
2219
options ??= new ArchiveOptions();
2320
options.LeaveOpen = true;
24-
await ArchiveFilesAsync(stream, files, options);
21+
await ArchiveFilesAsync(stream, entries, options);
2522
stream.Position = 0;
2623
return stream;
2724
}
2825

2926
/// <summary>
3027
/// <inheritdoc/>
3128
/// </summary>
32-
/// <param name="archiveFile">归档文件</param>
33-
/// <param name="files">要归档的文件集合</param>
34-
/// <param name="options">归档配置</param>
35-
public async Task ArchiveAsync(string archiveFile, IEnumerable<string> files, ArchiveOptions? options = null)
29+
public async Task ArchiveAsync(string archiveFile, IEnumerable<ArchiveEntry> entries, ArchiveOptions? options = null)
3630
{
3731
using var stream = File.OpenWrite(archiveFile);
38-
await ArchiveFilesAsync(stream, files, options);
32+
await ArchiveFilesAsync(stream, entries, options);
3933
}
4034

41-
private static async Task ArchiveFilesAsync(Stream stream, IEnumerable<string> files, ArchiveOptions? options = null)
35+
private static async Task ArchiveFilesAsync(Stream stream, IEnumerable<ArchiveEntry> entries, ArchiveOptions? options = null)
4236
{
4337
options ??= new ArchiveOptions();
4438
using var archive = new ZipArchive(stream, options.Mode, options.LeaveOpen, options.Encoding);
45-
foreach (var f in files)
39+
foreach (var f in entries)
4640
{
4741
if (options.ReadStreamAsync != null)
4842
{
49-
var entry = archive.CreateEntry(Path.GetFileName(f), options.CompressionLevel);
50-
using var entryStream = entry.Open();
51-
await using var content = await options.ReadStreamAsync(f);
43+
var entry = archive.CreateEntry(f.EntryName, options.CompressionLevel);
44+
await using var content = await options.ReadStreamAsync(f.SourceFileName);
45+
await using var entryStream = entry.Open();
5246
await content.CopyToAsync(entryStream);
47+
entryStream.Close();
48+
}
49+
else if (Directory.Exists(f.SourceFileName))
50+
{
51+
var entryName = f.EntryName;
52+
if (!string.IsNullOrEmpty(entryName))
53+
{
54+
if (!entryName.EndsWith(Path.DirectorySeparatorChar))
55+
{
56+
entryName = $"{entryName}{Path.DirectorySeparatorChar}";
57+
}
58+
archive.CreateEntry(entryName, f.CompressionLevel ?? options.CompressionLevel);
59+
}
5360
}
5461
else
5562
{
56-
archive.CreateEntryFromFile(f, Path.GetFileName(f), options.CompressionLevel);
63+
archive.CreateEntryFromFile(f.SourceFileName, f.EntryName, f.CompressionLevel ?? options.CompressionLevel);
5764
}
5865
}
5966
}
6067

6168
/// <summary>
6269
/// <inheritdoc/>
6370
/// </summary>
64-
/// <param name="archiveFile"></param>
65-
/// <param name="directoryName"></param>
66-
/// <param name="compressionLevel"></param>
67-
/// <param name="includeBaseDirectory"></param>
68-
/// <param name="encoding"></param>
69-
/// <param name="token"></param>
70-
/// <returns></returns>
71-
/// <exception cref="NotImplementedException"></exception>
72-
public async Task ArchiveDirectory(string archiveFile, string directoryName, CompressionLevel compressionLevel = CompressionLevel.Optimal, bool includeBaseDirectory = false, Encoding? encoding = null, CancellationToken token = default)
71+
public async Task ArchiveDirectoryAsync(string archiveFile, string directoryName, CompressionLevel compressionLevel = CompressionLevel.Optimal, bool includeBaseDirectory = false, Encoding? encoding = null, CancellationToken token = default)
7372
{
7473
if (Directory.Exists(directoryName))
7574
{
@@ -93,77 +92,6 @@ await Task.Run(() =>
9392
/// <summary>
9493
/// <inheritdoc/>
9594
/// </summary>
96-
/// <param name="archiveFile">归档文件</param>
97-
/// <param name="entries"></param>
98-
/// <param name="compressionLevel"></param>
99-
/// <param name="encoding"></param>
100-
/// <param name="skipEmptyFolder"></param>
101-
/// <param name="token"></param>
102-
/// <returns></returns>
103-
/// <exception cref="NotImplementedException"></exception>
104-
public async Task ArchiveDirectory(string archiveFile, IEnumerable<string> entries, CompressionLevel compressionLevel = CompressionLevel.Optimal, Encoding? encoding = null, bool skipEmptyFolder = false, CancellationToken token = default)
105-
{
106-
using var archive = ZipFile.Open(archiveFile, ZipArchiveMode.Create, encoding);
107-
108-
foreach (var entry in entries)
109-
{
110-
if (Directory.Exists(entry))
111-
{
112-
AddFolderToZip(archive, entry, Path.GetFileName(entry), compressionLevel);
113-
}
114-
else if (File.Exists(entry))
115-
{
116-
archive.CreateEntryFromFile(entry, Path.GetFileName(entry), compressionLevel);
117-
}
118-
}
119-
}
120-
121-
private static void AddFolderToZip(ZipArchive archive, string folderPath, string relativePath, CompressionLevel compressionLevel = CompressionLevel.Optimal)
122-
{
123-
archive.CreateEntry($"{relativePath}/", compressionLevel);
124-
125-
// 添加当前文件夹中的所有文件
126-
foreach (string filePath in Directory.GetFiles(folderPath))
127-
{
128-
string entryName = Path.Combine(relativePath, Path.GetFileName(filePath));
129-
archive.CreateEntryFromFile(filePath, entryName, compressionLevel);
130-
}
131-
132-
// 递归添加所有子文件夹
133-
foreach (string subfolderPath in Directory.GetDirectories(folderPath))
134-
{
135-
string newRelativePath = Path.Combine(relativePath, Path.GetFileName(subfolderPath));
136-
AddFolderToZip(archive, subfolderPath, newRelativePath, compressionLevel);
137-
}
138-
}
139-
140-
/// <summary>
141-
/// <inheritdoc/>
142-
/// </summary>
143-
/// <param name="archiveFile">归档文件</param>
144-
/// <param name="destinationDirectoryName">解压缩文件夹</param>
145-
/// <param name="overwriteFiles">是否覆盖文件 默认 false 不覆盖</param>
146-
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
147-
/// <returns></returns>
148-
public bool ExtractToDirectory(string archiveFile, string destinationDirectoryName, bool overwriteFiles = false, Encoding? encoding = null)
149-
{
150-
if (!Directory.Exists(destinationDirectoryName))
151-
{
152-
Directory.CreateDirectory(destinationDirectoryName);
153-
}
154-
ZipFile.ExtractToDirectory(archiveFile, destinationDirectoryName, encoding, overwriteFiles);
155-
return true;
156-
}
157-
158-
/// <summary>
159-
/// <inheritdoc/>
160-
/// </summary>
161-
/// <param name="archiveFile"></param>
162-
/// <param name="destinationDirectoryName"></param>
163-
/// <param name="overwriteFiles"></param>
164-
/// <param name="encoding"></param>
165-
/// <param name="token"></param>
166-
/// <returns></returns>
16795
public async Task<bool> ExtractToDirectoryAsync(string archiveFile, string destinationDirectoryName, bool overwriteFiles = false, Encoding? encoding = null, CancellationToken token = default)
16896
{
16997
if (!Directory.Exists(destinationDirectoryName))
@@ -186,11 +114,6 @@ await Task.Run(() =>
186114
/// <summary>
187115
/// <inheritdoc/>
188116
/// </summary>
189-
/// <param name="archiveFile">归档文件</param>
190-
/// <param name="entryFile">解压缩文件</param>
191-
/// <param name="overwriteFiles">是否覆盖文件 默认 false 不覆盖</param>
192-
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
193-
/// <returns></returns>
194117
public ZipArchiveEntry? GetEntry(string archiveFile, string entryFile, bool overwriteFiles = false, Encoding? encoding = null)
195118
{
196119
using var archive = ZipFile.Open(archiveFile, ZipArchiveMode.Read, encoding);

src/BootstrapBlazor/Services/IZipArchiveService.cs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ public interface IZipArchiveService
1616
/// <summary>
1717
/// 将文件归档方法
1818
/// </summary>
19-
/// <param name="files">要归档的文件集合</param>
19+
/// <param name="entries">要归档的文件集合</param>
2020
/// <param name="options">归档配置</param>
2121
/// <returns>归档数据流</returns>
22-
Task<Stream> ArchiveAsync(IEnumerable<string> files, ArchiveOptions? options = null);
22+
Task<Stream> ArchiveAsync(IEnumerable<ArchiveEntry> entries, ArchiveOptions? options = null);
2323

2424
/// <summary>
2525
/// 将文件归档方法
2626
/// </summary>
2727
/// <param name="archiveFile">归档文件</param>
28-
/// <param name="files">要归档的文件集合</param>
28+
/// <param name="entries">要归档的文件集合</param>
2929
/// <param name="options">归档配置</param>
30-
Task ArchiveAsync(string archiveFile, IEnumerable<string> files, ArchiveOptions? options = null);
30+
Task ArchiveAsync(string archiveFile, IEnumerable<ArchiveEntry> entries, ArchiveOptions? options = null);
3131

3232
/// <summary>
3333
/// 将指定目录归档方法
@@ -38,30 +38,7 @@ public interface IZipArchiveService
3838
/// <param name="includeBaseDirectory">是否包含本目录 默认 false</param>
3939
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
4040
/// <param name="token"></param>
41-
/// <returns></returns>
42-
Task ArchiveDirectory(string archiveFile, string directoryName, CompressionLevel compressionLevel = CompressionLevel.Optimal, bool includeBaseDirectory = false, Encoding? encoding = null, CancellationToken token = default);
43-
44-
/// <summary>
45-
/// 将指定目录归档方法
46-
/// </summary>
47-
/// <param name="archiveFile">归档文件</param>
48-
/// <param name="entries">要归档条目</param>
49-
/// <param name="compressionLevel">压缩率</param>
50-
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
51-
/// <param name="skipEmptyFolder">是否跳过空文件夹</param>
52-
/// <param name="token"></param>
53-
/// <returns></returns>
54-
Task ArchiveDirectory(string archiveFile, IEnumerable<string> entries, CompressionLevel compressionLevel = CompressionLevel.Optimal, Encoding? encoding = null, bool skipEmptyFolder = false, CancellationToken token = default);
55-
56-
/// <summary>
57-
/// 解压缩归档文件到指定文件夹
58-
/// </summary>
59-
/// <param name="archiveFile">归档文件</param>
60-
/// <param name="destinationDirectoryName">解压缩文件夹</param>
61-
/// <param name="overwriteFiles">是否覆盖文件 默认 false 不覆盖</param>
62-
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
63-
/// <returns></returns>
64-
bool ExtractToDirectory(string archiveFile, string destinationDirectoryName, bool overwriteFiles = false, Encoding? encoding = null);
41+
Task ArchiveDirectoryAsync(string archiveFile, string directoryName, CompressionLevel compressionLevel = CompressionLevel.Optimal, bool includeBaseDirectory = false, Encoding? encoding = null, CancellationToken token = default);
6542

6643
/// <summary>
6744
/// 解压缩归档文件到指定文件夹异步方法
@@ -71,7 +48,6 @@ public interface IZipArchiveService
7148
/// <param name="overwriteFiles">是否覆盖文件 默认 false 不覆盖</param>
7249
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
7350
/// <param name="token"></param>
74-
/// <returns></returns>
7551
Task<bool> ExtractToDirectoryAsync(string archiveFile, string destinationDirectoryName, bool overwriteFiles = false, Encoding? encoding = null, CancellationToken token = default);
7652

7753
/// <summary>
@@ -81,6 +57,26 @@ public interface IZipArchiveService
8157
/// <param name="entryFile">解压缩文件</param>
8258
/// <param name="overwriteFiles">是否覆盖文件 默认 false 不覆盖</param>
8359
/// <param name="encoding">编码方式 默认 null 内部使用 UTF-8</param>
84-
/// <returns></returns>
8560
ZipArchiveEntry? GetEntry(string archiveFile, string entryFile, bool overwriteFiles = false, Encoding? encoding = null);
8661
}
62+
63+
/// <summary>
64+
/// 归档项实体类
65+
/// </summary>
66+
public readonly record struct ArchiveEntry
67+
{
68+
/// <summary>
69+
/// 获得 物理文件
70+
/// </summary>
71+
public string SourceFileName { get; init; }
72+
73+
/// <summary>
74+
/// 获得 归档项
75+
/// </summary>
76+
public string EntryName { get; init; }
77+
78+
/// <summary>
79+
/// 获得 压缩配置
80+
/// </summary>
81+
public CompressionLevel? CompressionLevel { get; init; }
82+
}

0 commit comments

Comments
 (0)