如何在 Azure 文件存储文件夹中删除所有文件?

9
我正在努力学习如何删除Azure文件存储中文件夹中的所有文件。 CloudFileDirectory.ListFilesAndDirectories()返回一个IEnumerable类型的IListFileItem对象。但这并没有什么帮助,因为它没有文件名属性或类似的内容。
以下是我到目前为止所做的事情:
var folder = root.GetDirectoryReference("myfolder");

if (folder.Exists()) {
    foreach (var file in folder.ListFilesAndDirectories()) {

        // How do I delete 'file'

    }
}

如何将 IListFileItem 转换为 CloudFile,以便我可以调用 myfile.Delete()

7个回答

16

ListFilesAndDirectories 可以返回文件和目录,所以你可以得到这两个的基类。然后你可以检查它是哪种类型并转换。请注意,您需要跟踪任何子目录,以便可以递归地删除其中的文件。

var folder = root.GetDirectoryReference("myfolder");

if (folder.Exists())
{
    foreach (var item in folder.ListFilesAndDirectories())
    {         
        if (item.GetType() == typeof(CloudFile))
        {
            CloudFile file = (CloudFile)item;

            // Do whatever
        }

        else if (item.GetType() == typeof(CloudFileDirectory))
        {
            CloudFileDirectory dir = (CloudFileDirectory)item;

            // Do whatever
        }
    }
}

1
太好了,谢谢!我想知道这是否是正确的方法,但是关于IListFileItem的MSDN文档真的很差。 - BG100
1
谢谢!我必须承认,关于所有C#存储账户的文档都非常糟糕! - Carl

6

借鉴现有的答案,在修复一些错误后,创建了一个递归删除目录的扩展方法。

public static async Task DeleteAllAsync(this ShareDirectoryClient dirClient) {

    await foreach (ShareFileItem item in dirClient.GetFilesAndDirectoriesAsync()) {
        if (item.IsDirectory) {
            var subDir = dirClient.GetSubdirectoryClient(item.Name);
            await subDir.DeleteAllAsync();
        } else {
            await dirClient.DeleteFileAsync(item.Name);
        }
    }

    await dirClient.DeleteAsync();
}

按照调用方式

var dirClient = shareClient.GetDirectoryClient("test");
await dirClient.DeleteAllAsync();

为什么要使用队列?为什么不能直接使用 await foreach 循环? - Sugar Bowl
1
@SugarBowl - 你说得对。队列不是必需的。我复制并修改了其他答案中的一个来创建这个扩展方法,没有注意到这一点。我已经更新了答案。感谢你指出这个问题。 - Brad Patton
1
这是使用Azure文件共享的正确方式。 - Sugar Bowl

2

如果您的“目录”中有“子目录”,则此递归版本可用。

       public void DeleteOutputDirectory()
       {
           var share = _fileClient.GetShareReference(_settings.FileShareName);
           var rootDir = share.GetRootDirectoryReference();

           DeleteDirectory(rootDir.GetDirectoryReference("DirName"));
       }

       private static void DeleteDirectory(CloudFileDirectory directory)
       {
           if (directory.Exists())
           {
               foreach (IListFileItem item in directory.ListFilesAndDirectories())
               {
                   switch (item)
                   {
                       case CloudFile file:
                           file.Delete();
                           break;
                       case CloudFileDirectory dir:
                           DeleteDirectory(dir);
                           break;
                   }
               }

               directory.Delete();
           }
       }

1

0
  1. 使用虚拟机连接到您的 Azure 容器(如果是文件共享,则转到文件共享 > 连接,并按照命令将其粘贴到虚拟机中 - 以连接到文件共享)
  2. 在虚拟机命令界面中连接到您的容器(cd '容器所在位置')
  3. 删除文件夹(rm -rf '要删除的文件夹')

0

现在,被接受的答案似乎已经过时了。以下代码使用了最新的SDK。为了获得更好的性能,它是通过for循环实现而不是递归算法。它会发现位于directoryPath的所有文件和文件夹。一旦发现一个文件,就可以将其删除。

var rootDirectory = directoryPath != null 
? shareClient.GetDirectoryClient(directoryPath)
: shareClient.GetRootDirectoryClient();

var remaining = new Queue<ShareDirectoryClient>();
remaining.Enqueue(rootDirectory);

while (remaining.Count > 0)
{
    var shareDirectoryClient = remaining.Dequeue();

     await foreach (var item in shareDirectoryClient.GetFilesAndDirectoriesAsync())
     {
          if (!item.IsDirectory)
          {
              var shareFileClient = shareDirectoryClient.GetFileClient(item.Name);
                    files.Add(shareFileClient);
              // do what you want
              await shareFile.DeleteAsync();
          }

          if (item.IsDirectory)
          {
              remaining.Enqueue(shareDirectoryClient.GetSubdirectoryClient(item.Name));
              // do what you want
              await shareFile.DeleteAsync();
          }
     }
}

在上述代码中,directory 可能为 null 或者是你想要删除的目录路径。
要初始化客户端,您可以使用以下方法:
AccountSasBuilder sas = new AccountSasBuilder
{
    Services = AccountSasServices.Files,
    ResourceTypes = AccountSasResourceTypes.All,
    ExpiresOn = DateTimeOffset.UtcNow.AddMonths(1)
};

 sas.SetPermissions(AccountSasPermissions.List | AccountSasPermissions.Read | AccountSasPermissions.Delete);

var credential = new StorageSharedKeyCredential(AccountName, AccountKey);
var sasUri = new UriBuilder(AccountUri);
sasUri.Query = sas.ToSasQueryParameters(credential).ToString();

var shareServiceClient = new ShareServiceClient(sasUri.Uri);
var shareClient = shareServiceClient.GetShareClient(FileShareName);
   

那行不通 - 第一个代码示例中充满了错别字和错误。 - Miros

0

这个方法应该可以解决问题 - 如果我错了或者有任何改进的地方,请评论。

public async override Task DeleteFolder(string storagePath)
{
    var remaining = new Queue<ShareDirectoryClient>();
    remaining.Enqueue(Share.GetDirectoryClient(storagePath));

    while(remaining.Count > 0)
    {
        ShareDirectoryClient dir = remaining.Dequeue();

        await foreach (ShareFileItem item in dir.GetFilesAndDirectoriesAsync())
        {
            if(item.IsDirectory)
            {
                var subDir = dir.GetSubdirectoryClient(item.Name);
                await DeleteFolder(subDir.Path);
            }
            else
            {
                await dir
                    .GetFileClient(item.Name)
                    .DeleteAsync();
            }
        }

        await dir.DeleteAsync();
    }
}

顺便说一句(微软你在看吗?),这是使用Dropbox API V2的方法:using(var client = await GetClient()) { var res = await client.Files.DeleteV2Async(storagePath); } - Miros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接