feat: Vue Router 集成 + 压缩密码编码修复
前端: - 引入 vue-router,HTML5 History 模式,干净 URL - ClientPage.vue 拆分为 5 个独立路由视图组件 - 提取共享状态到 composables(useLibraryRoots/useMediaPlayer/useViewMode/useModals) - 新增 DefaultLayout 统一布局 - 导航链接改为 router-link - FileCard 网格视图修复删除/压缩按钮 hover 不显示问题 后端: - 压缩密码编码修复:DotNetZip/SharpZipLib 不支持 UTF-8 密码 - 替换为 SharpZipLib + 中文字符替换为 # 的 ASCII 安全密码方案
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.7" />
|
||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="QRCoder" Version="1.8.0" />
|
||||
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
|
||||
@@ -2,7 +2,7 @@ using FileShare_Common.Core;
|
||||
using FileShare_EFCore.Database;
|
||||
using FileShare_EFCore.Models;
|
||||
using FileShare_Services.Core;
|
||||
using Ionic.Zip;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Text;
|
||||
|
||||
@@ -614,14 +614,25 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
File.Delete(zipPath);
|
||||
}
|
||||
|
||||
// 密码为文件名去掉后缀
|
||||
var zipPassword = nameWithoutExt.ToLower();
|
||||
// 密码为文件名去掉后缀(中文转拼音,转小写)
|
||||
var zipPassword = ConvertToAsciiPassword(nameWithoutExt);
|
||||
|
||||
// 创建 ZIP
|
||||
using var zip = new Ionic.Zip.ZipFile();
|
||||
zip.Password = zipPassword;
|
||||
zip.AddFile(record.AbsolutePath, "");
|
||||
zip.Save(zipPath);
|
||||
// 使用 SharpZipLib 创建加密 ZIP(支持 UTF-8 密码)
|
||||
using var outputStream = File.Create(zipPath);
|
||||
using var zipStream = new ZipOutputStream(outputStream);
|
||||
zipStream.Password = zipPassword;
|
||||
zipStream.UseZip64 = UseZip64.Dynamic;
|
||||
|
||||
var entry = new ZipEntry(Path.GetFileName(record.AbsolutePath));
|
||||
entry.DateTime = File.GetLastWriteTime(record.AbsolutePath);
|
||||
zipStream.PutNextEntry(entry);
|
||||
|
||||
using (var fileStream = File.OpenRead(record.AbsolutePath))
|
||||
{
|
||||
await fileStream.CopyToAsync(zipStream, cancellationToken);
|
||||
}
|
||||
|
||||
zipStream.CloseEntry();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -881,6 +892,22 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
|| sortDirection?.Trim().Equals("descending", StringComparison.OrdinalIgnoreCase) == true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将文件名转换为 ASCII 安全的密码。中文字符替换为 #,其他字符保留原样。
|
||||
/// </summary>
|
||||
private static string ConvertToAsciiPassword(string fileName)
|
||||
{
|
||||
var sb = new StringBuilder(fileName.Length);
|
||||
foreach (var ch in fileName)
|
||||
{
|
||||
if (ch >= 0x4E00 && ch <= 0x9FFF)
|
||||
sb.Append('#');
|
||||
else
|
||||
sb.Append(ch);
|
||||
}
|
||||
return sb.ToString().ToLower();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全获取驱动器属性值,驱动器未就绪或访问异常时返回 null。
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user