Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/BootstrapBlazor.Server/Components/Samples/ZipArchives.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/zip-archive"
@page "/zip-archive"
@layout MainLayout
@inject IStringLocalizer<ZipArchives> Localizer

Expand All @@ -13,10 +13,14 @@ private IZipArchiveService? ZipArchiveService { get; set; }</Pre>
<p>@Localizer["ZipArchiveFileText"]</p>
<Pre class="mb-3">Task&lt;Stream&gt; ArchiveAsync(IEnumerable&lt;string&gt; files, ArchiveOptions? options = null);

Task ArchiveAsync(string archiveFileName, IEnumerable&lt;string&gt; files, ArchiveOptions? options = null);</Pre>
Task ArchiveAsync(string archiveFile, IEnumerable&lt;string&gt; files, ArchiveOptions? options = null);

Task&lt;Stream&gt; ArchiveAsync(IEnumerable&lt;ArchiveEntry&gt; entries, ArchiveOptions? options = null);

Task ArchiveAsync(string archiveFile, IEnumerable&lt;ArchiveEntry&gt; entries, ArchiveOptions? options = null);</Pre>

<p>@Localizer["ZipArchiveDirectoryText"]</p>
<Pre class="mb-3">Task ArchiveDirectory(string archiveFileName, string directoryName, CompressionLevel compressionLevel = CompressionLevel.Optimal, bool includeBaseDirectory = false, Encoding? encoding = null);</Pre>
<Pre class="mb-3">Task ArchiveDirectoryAsync(string archiveFile, string directoryName, CompressionLevel compressionLevel = CompressionLevel.Optimal, bool includeBaseDirectory = false, Encoding? encoding = null);</Pre>

<p>@Localizer["ZipArchiveExtractText"]</p>
<Pre class="mb-3">bool ExtractToDirectory(string archiveFile, string destinationDirectoryName, bool overwriteFiles = false, Encoding? encoding = null);</Pre>
<Pre class="mb-3">Task&lt;bool&gt; ExtractToDirectoryAsync(string archiveFile, string destinationDirectoryName, bool overwriteFiles = false, Encoding? encoding = null);</Pre>
Comment thread
ArgoZhang marked this conversation as resolved.
36 changes: 29 additions & 7 deletions src/BootstrapBlazor/Services/DefaultZipArchiveService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ namespace BootstrapBlazor.Components;

class DefaultZipArchiveService : IZipArchiveService
{
/// <summary>
/// <inheritdoc/>
/// </summary>
Comment thread
ArgoZhang marked this conversation as resolved.
public Task<Stream> ArchiveAsync(IEnumerable<string> files, ArchiveOptions? options = null) => ArchiveAsync(files.Select(f => new ArchiveEntry()
{
SourceFileName = f,
EntryName = Path.GetFileName(f),
}), options);

/// <summary>
/// <inheritdoc/>
/// </summary>
Comment thread
ArgoZhang marked this conversation as resolved.
public Task ArchiveAsync(string archiveFile, IEnumerable<string> files, ArchiveOptions? options = null) => ArchiveAsync(archiveFile, files.Select(f => new ArchiveEntry()
{
SourceFileName = f,
EntryName = Path.GetFileName(f),
}), options);

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand All @@ -28,7 +46,7 @@ public async Task<Stream> ArchiveAsync(IEnumerable<ArchiveEntry> entries, Archiv
/// </summary>
public async Task ArchiveAsync(string archiveFile, IEnumerable<ArchiveEntry> entries, ArchiveOptions? options = null)
{
using var stream = File.OpenWrite(archiveFile);
await using var stream = File.OpenWrite(archiveFile);
await ArchiveFilesAsync(stream, entries, options);
}

Expand All @@ -38,6 +56,11 @@ private static async Task ArchiveFilesAsync(Stream stream, IEnumerable<ArchiveEn
using var archive = new ZipArchive(stream, options.Mode, options.LeaveOpen, options.Encoding);
foreach (var f in entries)
{
if (string.IsNullOrEmpty(f.EntryName))
{
continue;
}

if (options.ReadStreamAsync != null)
{
var entry = archive.CreateEntry(f.EntryName, options.CompressionLevel);
Expand All @@ -48,14 +71,13 @@ private static async Task ArchiveFilesAsync(Stream stream, IEnumerable<ArchiveEn
else if (Directory.Exists(f.SourceFileName))
{
var entryName = f.EntryName;
if (!string.IsNullOrEmpty(entryName))

if (!entryName.EndsWith('/'))
{
if (!entryName.EndsWith('/'))
{
entryName = $"{entryName}/";
}
archive.CreateEntry(entryName, f.CompressionLevel ?? options.CompressionLevel);
entryName = $"{entryName}/";
}

archive.CreateEntry(entryName, f.CompressionLevel ?? options.CompressionLevel);
}
else if (File.Exists(f.SourceFileName))
{
Expand Down
16 changes: 16 additions & 0 deletions src/BootstrapBlazor/Services/IZipArchiveService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ namespace BootstrapBlazor.Components;
/// </summary>
public interface IZipArchiveService
{
/// <summary>
/// 将文件归档方法
/// </summary>
/// <param name="files">要归档的文件集合</param>
/// <param name="options">归档配置</param>
/// <returns>归档数据流</returns>
Task<Stream> ArchiveAsync(IEnumerable<string> files, ArchiveOptions? options = null);

/// <summary>
/// 将文件归档方法
/// </summary>
/// <param name="archiveFile">归档文件</param>
/// <param name="files">要归档的文件集合</param>
/// <param name="options">归档配置</param>
Task ArchiveAsync(string archiveFile, IEnumerable<string> files, ArchiveOptions? options = null);

/// <summary>
/// 将文件归档方法
/// </summary>
Expand Down
48 changes: 36 additions & 12 deletions test/UnitTest/Services/ZipArchiveServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public async Task Archive_Ok()
{
var archService = Context.Services.GetRequiredService<IZipArchiveService>();
var root = AppContext.BaseDirectory;
var files = new string[]
var files = new[]
{
Path.Combine(root, "1.txt"),
Path.Combine(root, "2.txt")
Expand All @@ -28,16 +28,16 @@ public async Task Archive_Ok()
{
SourceFileName = i,
EntryName = Path.GetFileName(i)
});
}).ToList();
var stream = await archService.ArchiveAsync(items);
Assert.NotNull(stream);

stream = await archService.ArchiveAsync(items, new ArchiveOptions()
{
CompressionLevel = System.IO.Compression.CompressionLevel.Optimal,
CompressionLevel = CompressionLevel.Optimal,
Encoding = System.Text.Encoding.UTF8,
Mode = System.IO.Compression.ZipArchiveMode.Create,
ReadStreamAsync = f => Task.FromResult<Stream>(new MemoryStream("A"u8.ToArray()))
Mode = ZipArchiveMode.Create,
ReadStreamAsync = _ => Task.FromResult<Stream>(new MemoryStream("A"u8.ToArray()))
});
Assert.NotNull(stream);

Expand Down Expand Up @@ -93,8 +93,8 @@ public async Task ZipArchive_Ok()
File.Delete(fileName);
}

using var fs = File.OpenWrite(fileName);
using var zip = new ZipArchive(fs, ZipArchiveMode.Create);
await using var fs = File.OpenWrite(fileName);
await using var zip = new ZipArchive(fs, ZipArchiveMode.Create);

var item = Path.Combine(AppContext.BaseDirectory, "test", "1.txt");
zip.CreateEntry("text/");
Expand All @@ -111,7 +111,7 @@ public async Task ArchiveAsync_Ok()
}

var root = AppContext.BaseDirectory;
var files = new string[]
var files = new[]
{
Path.Combine(root, "archive_test", "test1", "1.txt"),
Path.Combine(root, "archive_test", "test2", "2.txt")
Expand All @@ -130,30 +130,54 @@ public async Task ArchiveAsync_Ok()
var archService = Context.Services.GetRequiredService<IZipArchiveService>();
await archService.ArchiveAsync(fileName, new List<ArchiveEntry>()
{
new ArchiveEntry()
new()
{
SourceFileName = files[0],
EntryName = "test1/test.log"
},
new ArchiveEntry()
new()
{
SourceFileName = files[1],
EntryName = "test2/test.log",
CompressionLevel = CompressionLevel.Optimal
},
new ArchiveEntry()
new()
{
SourceFileName = Path.Combine(AppContext.BaseDirectory, "archive_test", "test1"),
EntryName = "test1",
},
new ArchiveEntry()
new()
{
SourceFileName = Path.Combine(AppContext.BaseDirectory, "archive_test", "test1"),
EntryName = "test2",
CompressionLevel = CompressionLevel.Optimal
},
new()
{
SourceFileName = files[1]
}
});

Assert.True(File.Exists(fileName));

if (File.Exists(fileName))
{
File.Delete(fileName);
}
Assert.False(File.Exists(fileName));
await archService.ArchiveAsync(fileName, new List<string>()
{
Path.Combine(AppContext.BaseDirectory, "archive_test", "test1", "test.log"),
Path.Combine(AppContext.BaseDirectory, "archive_test", "test2", "test.log")
});
Assert.True(File.Exists(fileName));

await using var stream = await archService.ArchiveAsync(new List<string>()
{
Path.Combine(AppContext.BaseDirectory, "archive_test", "test1", "test.log"),
Path.Combine(AppContext.BaseDirectory, "archive_test", "test2", "test.log")
});
Assert.NotNull(stream);
Assert.True(stream.Length != 0);
}
}