如何在Azure中移动目录并使用Azure文件共享中的ShareDirectoryClient对其进行压缩

pkwftd7m  于 2022-11-17  发布在  其他
关注(0)|答案(2)|浏览(142)

bounty将在3天后过期。回答此问题可获得+300的声望奖励。Billy正在寻找来自知名来源的答案

我可以使用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.");
        }

        static async Task RenameDirectory(ShareDirectoryClient sourceDirectoryClient,
            ShareDirectoryClient targetDirectoryClient)
        {
            //Create target directory
            await targetDirectoryClient.CreateIfNotExistsAsync();
            //List files and folders from the source directory
            var result = sourceDirectoryClient.GetFilesAndDirectoriesAsync();
            await foreach (var items in result.AsPages())
            {
                foreach (var item in items.Values)
                {
                    if (item.IsDirectory)
                    {
                        //If item is directory, then get the child items in that directory recursively.
                        await RenameDirectory(sourceDirectoryClient.GetSubdirectoryClient(item.Name),
                            targetDirectoryClient.GetSubdirectoryClient(item.Name));
                    }
                    else
                    {
                        //If item is file, then copy the file and then delete it.
                        var sourceFileClient = sourceDirectoryClient.GetFileClient(item.Name);
                        var targetFileClient = targetDirectoryClient.GetFileClient(item.Name);
                        await targetFileClient.StartCopyAsync(sourceFileClient.Uri);
                        await sourceFileClient.DeleteIfExistsAsync();
                    }
                }
            }
            //Delete source directory.
            await sourceDirectoryClient.DeleteIfExistsAsync();
        }
        
    }
}

我正在使用ShareDirectoryClient在Azure中移动目录。这里我们如何在移动后压缩文件夹。
我的方法:

using System.IO.Compression;
ZipFile.CreateFromDirectory(sourceDirectoryClient.Path, targetDirectoryClient.Path);

错误:无法找到路径“/app/NewFolder/ www.example.com”的一部分test.zip。
请协助我解决此问题
注意:我们也可以使用下面的库https://github.com/icsharpcode/SharpZipLib
使用C#和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");
}

上面的代码会将所有文件夹的内容压缩成一个新的zip文件。我们如何在azure sharedirectoryclient目录中实现同样的操作呢?

eeq64g8w

eeq64g8w1#

我的理解是,您希望从Azure文件共享压缩目录,并将结果zip存档存储在同一Azure文件共享上。
ZipFile.CreateFromDirectory的问题与路径和执行代码的位置有关。如果替换这些路径,将得到如下结果:

ZipFile.CreateFromDirectory("/app/NewFolder", "/app/NewFolder.zip");

这些路径被视为应用程序的本地路径(如果应用程序位于C:\MyApp中,则它们将解析为C:\MyApp\app\NewFolder)。ZipFile不使用Azure文件共享,这是主要问题。
您可以尝试使用Azure Data Factory来压缩文件夹,或者如果您想在代码中实现这一点,Josefs Ottosson tutorial可能会有所帮助。
或者,如果您将共享附加到运行应用的计算机上,则可以使用此方法,然后在此计算机上操作文件。

bf1o4zei

bf1o4zei2#

我修改了您的代码,使其包含zip文件创建和上载
这是你的Main方法。它现在包含了内存中的ZipArchive。Archive被传递到你的递归方法中,这样它就可以把列出的文件写入Zip流。
运行您的方法后,我们需要在共享上创建新文件并上传其内容

static async Task Main(string[] args)
{
    ShareClient myshare = new ShareClient(MyconnectionString, MyshareName);
    ShareDirectoryClient sourceDirectoryClient = myshare.GetDirectoryClient(SourceDirectoryName);
    ShareDirectoryClient targetDirectoryClient = myshare.GetDirectoryClient(RenamedDirectoryName);

    using (var memory = new MemoryStream())
    {
        using (var zip = new ZipArchive(memory, ZipArchiveMode.Create, true))
        {
            await RenameDirectory(sourceDirectoryClient, targetDirectoryClient, zip);
        }
        
        var zipfile = await myshare.GetRootDirectoryClient().CreateFileAsync(RenamedDirectoryName + ".zip", memory.Length);
        memory.Seek(0, SeekOrigin.Begin);
        await zipfile.Value.UploadAsync(memory);
    }
    Console.WriteLine("Directory renamed.");
}

您的RenameDirectory方法需要包括另一个参数path,以跟踪递归子目录遍历,该遍历用于命名zip存档中的文件(包括目录结构)。

static async Task RenameDirectory(ShareDirectoryClient sourceDirectoryClient,
    ShareDirectoryClient targetDirectoryClient, ZipArchive zip, string path = "")
{
    //Create target directory    
    await targetDirectoryClient.CreateIfNotExistsAsync();
    //List files and folders from the source directory
    var result = sourceDirectoryClient.GetFilesAndDirectoriesAsync();
    
    await foreach (var items in result.AsPages())
    {
        foreach (var item in items.Values)
        {
            if (item.IsDirectory)
            {
                //If item is directory, then get the child items in that directory recursively.
                await RenameDirectory(sourceDirectoryClient.GetSubdirectoryClient(item.Name),
                    targetDirectoryClient.GetSubdirectoryClient(item.Name), zip, $"{path}{item.Name}/");
            }
            else
            {
                //If item is file, then copy the file and then delete it.
                var sourceFileClient = sourceDirectoryClient.GetFileClient(item.Name);
                var targetFileClient = targetDirectoryClient.GetFileClient(item.Name);
                await targetFileClient.StartCopyAsync(sourceFileClient.Uri);
                
                var file = await sourceFileClient.DownloadAsync();
                var zipEntry = zip.CreateEntry(path + item.Name);
                using (var zipEntryStream = zipEntry.Open())
                {
                    await file.Value.Content.CopyToAsync(zipEntryStream);
                }
                
                await sourceFileClient.DeleteIfExistsAsync();
            }
        }
    }
    
    //Delete source directory.
    await sourceDirectoryClient.DeleteIfExistsAsync();
}

我保留了你所有的代码没有修改-所以旧的行为仍然存在(新的文件夹仍然会被创建,旧的将被删除)。额外的结果是,应用程序应该创建一个zip文件在根目录下的共享。我认为它应该很容易删除所有的'目标'文件夹和文件创建从你的代码(如果你不需要它了)。我希望这将是很容易识别的变化。
显然,我并没有试图将所有的zip构建封装到单独的IDisposable类中,以明确应该在哪里发生什么。
记住这一点- zip文件是在应用程序的内存中创建的。如果你有很多文件,那么应用程序的内存消耗可能会增长得很快-所以要小心!)
另一个建议是,你不应该删除任何文件从共享,直到你保存完整的zip。否则,在例外的情况下,你会失去文件已'移动'到内存中的zip。这可能意味着你将不得不遍历源文件夹两次,但它更安全。

相关问题