如何使用ShareDirectoryClient移动Azure文件共享目录并压缩
已实现的目录移动代码
我已成功使用ShareDirectoryClient完成Azure文件共享中目录的移动操作,相关代码如下:
using System; using System.Threading.Tasks; using Azure.Storage.Files.Shares; namespace SO69798149 { class Program { const string MyconnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key"; const string MyshareName = "share-name"; const string SourceDirectoryName = "source-directory-name"; private const string RenamedDirectoryName = "new-directory-name"; static async Task Main(string[] args) { ShareClient myshare = new ShareClient(MyconnectionString, MyshareName); ShareDirectoryClient sourceDirectoryClient = myshare.GetDirectoryClient(SourceDirectoryName); ShareDirectoryClient targetDirectoryClient = myshare.GetDirectoryClient(RenamedDirectoryName); await RenameDirectory(sourceDirectoryClient, targetDirectoryClient); Console.WriteLine("Directory renamed."); // 调用压缩方法 await CompressAzureDirectory(targetDirectoryClient, myshare.GetFileClient("compressed-directory.zip")); } static async Task RenameDirectory(ShareDirectoryClient sourceDirectoryClient, ShareDirectoryClient targetDirectoryClient) { // 创建目标目录 await targetDirectoryClient.CreateIfNotExistsAsync(); // 列出源目录下的所有文件和子目录 var result = sourceDirectoryClient.GetFilesAndDirectoriesAsync(); await foreach (var items in result.AsPages()) { foreach (var item in items.Values) { if (item.IsDirectory) { // 递归处理子目录 await RenameDirectory(sourceDirectoryClient.GetSubdirectoryClient(item.Name), targetDirectoryClient.GetSubdirectoryClient(item.Name)); } else { // 复制文件到目标目录后删除源文件 var sourceFileClient = sourceDirectoryClient.GetFileClient(item.Name); var targetFileClient = targetDirectoryClient.GetFileClient(item.Name); await targetFileClient.StartCopyAsync(sourceFileClient.Uri); await sourceFileClient.DeleteIfExistsAsync(); } } } // 删除源目录 await sourceDirectoryClient.DeleteIfExistsAsync(); } } }
压缩尝试遇到的问题
尝试使用System.IO.Compression.ZipFile进行压缩时,执行以下代码:
using System.IO.Compression; ZipFile.CreateFromDirectory(sourceDirectoryClient.Path, targetDirectoryClient.Path);
出现错误:Could not find a part of the path '/app/NewFolder/test.zip'.
我也了解到可以使用SharpZipLib库,其示例代码如下:
Zipping a directory using C# and SharpZipLib
void fastcompressDirectory(string DirectoryPath, string OutputFilePath, int CompressionLevel = 9) { ICSharpCode.SharpZipLib.Zip.FastZip z = new ICSharpCode.SharpZipLib.Zip.FastZip(); z.CreateEmptyDirectories = true; z.CreateZip(OutputFilePath, DirectoryPath, true, ""); if (File.Exists(OutputFilePath)) Console.WriteLine("D0ne"); else Console.WriteLine("Failed"); }
问题原因
无论是ZipFile.CreateFromDirectory还是SharpZipLib的FastZip.CreateZip,都是针对本地文件系统路径设计的,而ShareDirectoryClient.Path返回的是Azure文件共享中的逻辑路径(并非本地磁盘路径),因此这些方法无法直接识别和访问Azure上的目录内容,导致路径找不到的错误。
解决方案:本地临时目录中转压缩
要实现Azure文件共享目录的压缩,需要先将目录内容下载到本地临时目录,压缩后再上传回Azure文件共享,具体实现如下:
方法1:使用原生System.IO.Compression实现
添加以下异步压缩方法到你的代码中:
using System.IO; using System.IO.Compression; static async Task CompressAzureDirectory(ShareDirectoryClient sourceDirClient, ShareFileClient targetZipFileClient) { // 创建本地临时目录 string tempLocalDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempLocalDir); try { // 递归下载Azure目录到本地临时目录 await DownloadDirectoryToLocal(sourceDirClient, tempLocalDir); // 压缩本地临时目录到临时zip文件 string tempZipPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".zip"); ZipFile.CreateFromDirectory(tempLocalDir, tempZipPath, CompressionLevel.Optimal, includeBaseDirectory: false); // 将压缩后的zip文件上传到Azure文件共享 using (var stream = File.OpenRead(tempZipPath)) { await targetZipFileClient.UploadAsync(stream, overwrite: true); } Console.WriteLine("Directory compressed and uploaded successfully."); } finally { // 清理本地临时文件和目录 if (Directory.Exists(tempLocalDir)) Directory.Delete(tempLocalDir, recursive: true); foreach (var file in Directory.GetFiles(Path.GetTempPath(), "*.zip")) { File.Delete(file); } } } static async Task DownloadDirectoryToLocal(ShareDirectoryClient dirClient, string localDirPath) { // 创建本地目录 Directory.CreateDirectory(localDirPath); // 列出当前Azure目录下的所有项 var items = dirClient.GetFilesAndDirectoriesAsync(); await foreach (var page in items.AsPages()) { foreach (var item in page.Values) { if (item.IsDirectory) { // 递归下载子目录 var subDirClient = dirClient.GetSubdirectoryClient(item.Name); string subLocalDir = Path.Combine(localDirPath, item.Name); await DownloadDirectoryToLocal(subDirClient, subLocalDir); } else { // 下载文件到本地 var fileClient = dirClient.GetFileClient(item.Name); string localFilePath = Path.Combine(localDirPath, item.Name); await fileClient.DownloadToAsync(localFilePath); } } } }
方法2:使用SharpZipLib实现
- 先安装SharpZipLib NuGet包:
Install-Package ICSharpCode.SharpZipLib - 添加以下压缩方法:
using ICSharpCode.SharpZipLib.Zip; static async Task CompressAzureDirectoryWithSharpZipLib(ShareDirectoryClient sourceDirClient, ShareFileClient targetZipFileClient) { string tempLocalDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempLocalDir); try { await DownloadDirectoryToLocal(sourceDirClient, tempLocalDir); string tempZipPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".zip"); FastZip fastZip = new FastZip(); fastZip.CreateEmptyDirectories = true; // 压缩本地目录到zip文件 fastZip.CreateZip(tempZipPath, tempLocalDir, true, ""); // 上传zip到Azure using (var stream = File.OpenRead(tempZipPath)) { await targetZipFileClient.UploadAsync(stream, overwrite: true); } Console.WriteLine("Directory compressed with SharpZipLib and uploaded successfully."); } finally { // 清理本地资源 if (Directory.Exists(tempLocalDir)) Directory.Delete(tempLocalDir, recursive: true); foreach (var file in Directory.GetFiles(Path.GetTempPath(), "*.zip")) { File.Delete(file); } } }
使用方式
在Main方法中,目录移动完成后调用对应的压缩方法即可:
// 使用原生ZipFile压缩 await CompressAzureDirectory(targetDirectoryClient, myshare.GetFileClient("target-directory.zip")); // 或者使用SharpZipLib压缩 // await CompressAzureDirectoryWithSharpZipLib(targetDirectoryClient, myshare.GetFileClient("target-directory-sharp.zip"));
内容的提问来源于stack exchange,提问作者Billy
相关产品推荐
相关产品推荐

