使用锐盒下载文件

本文关键字:下载 文件 | 更新日期: 2023-09-27 18:34:17

所以我有一些代码可以递归创建目录并重复下载文件夹中的文件。

这是代码:

public class Program
    {
        static void UploadDownloadProgress(Object sender, FileDataTransferEventArgs e)
        { 
            // print a dot
            Console.WriteLine("Downloading");
            Console.WriteLine(".");
            // it's ok to go forward
            e.Cancel = false;
        } 
        public static void DownloadFolder(CloudStorage dropBoxStorage, ICloudDirectoryEntry remoteDir, string targetDir, string sourceDir)
        {           
            foreach (ICloudFileSystemEntry fsentry in remoteDir)
            {
                var filepath = Path.Combine(targetDir, fsentry.Name);
                if (fsentry is ICloudDirectoryEntry)
                {
                    Console.WriteLine("Created: {0}", filepath);
                    Directory.CreateDirectory(filepath);
                    DownloadFolder(dropBoxStorage, fsentry as ICloudDirectoryEntry, filepath, sourceDir);
                }
                else
                {
                    dropBoxStorage.DownloadFile(remoteDir, fsentry.Name, targetDir, UploadDownloadProgress);
                }
            }
        }
        static void Main(string[] args)
        {
            CloudStorage dropBoxStorage = new CloudStorage();
            var dropBixConfig = CloudStorage.GetCloudConfigurationEasy(nSupportedCloudConfigurations.DropBox);
            ICloudStorageAccessToken accessToken = null;
            using (FileStream fs = File.Open(@"C:'Users'Michael'token.txt", FileMode.Open, FileAccess.Read, FileShare.None))
            {
                accessToken = dropBoxStorage.DeserializeSecurityToken(fs);
            }
            var storageToken = dropBoxStorage.Open(dropBixConfig, accessToken);
            //do stuff
            //var root = dropBoxStorage.GetRoot();
            var publicFolder = dropBoxStorage.GetFolder("/Public");
            foreach (var folder in publicFolder)
            {
                Boolean bIsDirectory = folder is ICloudDirectoryEntry;
                Console.WriteLine("{0}: {1}", bIsDirectory ? "DIR" : "FIL", folder.Name);
            }
            string remoteDirName = @"/Public/IQSWS";
            string targetDir = @"C:'Users'Michael'";
            var remoteDir = dropBoxStorage.GetFolder(remoteDirName);
            DownloadFolder(dropBoxStorage, remoteDir, targetDir, remoteDirName);
            dropBoxStorage.Close();
        }
        public delegate void FileOperationProgressChanged(object sender, FileDataTransferEventArgs e);    
    }

循环在else中找到第一个文件后,它会下载它,然后移动到下一个文件,但是它会在foreach上抛出异常:

System.InvalidOperationException was unhandled
  HResult=-2146233079
  Message=Collection was modified; enumeration operation may not execute.
  Source=mscorlib
  StackTrace:
       at System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.MoveNext()
       at StartServer.Program.DownloadFolder(CloudStorage dropBoxStorage, ICloudDirectoryEntry remoteDir, String targetDir, String sourceDir) in c:'Users'Michael'Documents'Visual Studio 2012'Projects'IQS Source'StartServer'StartServer'Program.cs:line 29
       at StartServer.Program.DownloadFolder(CloudStorage dropBoxStorage, ICloudDirectoryEntry remoteDir, String targetDir, String sourceDir) in c:'Users'Michael'Documents'Visual Studio 2012'Projects'IQS Source'StartServer'StartServer'Program.cs:line 39
       at StartServer.Program.DownloadFolder(CloudStorage dropBoxStorage, ICloudDirectoryEntry remoteDir, String targetDir, String sourceDir) in c:'Users'Michael'Documents'Visual Studio 2012'Projects'IQS Source'StartServer'StartServer'Program.cs:line 39
       at StartServer.Program.DownloadFolder(CloudStorage dropBoxStorage, ICloudDirectoryEntry remoteDir, String targetDir, String sourceDir) in c:'Users'Michael'Documents'Visual Studio 2012'Projects'IQS Source'StartServer'StartServer'Program.cs:line 39
       at StartServer.Program.Main(String[] args) in c:'Users'Michael'Documents'Visual Studio 2012'Projects'IQS Source'StartServer'StartServer'Program.cs:line 80
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

为什么会这样?当我所做的只是下载文件时,为什么要编辑数组?

使用锐盒下载文件

您将整个集合remoteDir传递到 DownloadFile 方法中,该方法如下所示:

// AppLimit.CloudComputing.SharpBox.CloudStorage
public void DownloadFile(ICloudDirectoryEntry parent, string name, string targetPath, FileOperationProgressChanged delProgress)
{
    if (parent == null || name == null || targetPath == null)
    {
        throw new SharpBoxException(SharpBoxErrorCodes.ErrorInvalidParameters);
    }
    targetPath = Environment.ExpandEnvironmentVariables(targetPath);
    ICloudFileSystemEntry child = parent.GetChild(name);
    using (FileStream fileStream = new FileStream(Path.Combine(targetPath, name), FileMode.Create, FileAccess.Write, FileShare.None))
    {
        child.GetDataTransferAccessor().Transfer(fileStream, nTransferDirection.nDownload, delProgress, null);
    }
}

此方法中可以修改parent的唯一点似乎是它调用GetChild的位置。看看GetChild(我用了IlSpy):

public ICloudFileSystemEntry GetChild(string name)
{
  return this.GetChild(name, true);
}
public ICloudFileSystemEntry GetChild(string name, bool bThrowException)
{
  this.RefreshResource();
  ICloudFileSystemEntry cloudFileSystemEntry;
  this._subDirectories.TryGetValue(name, out cloudFileSystemEntry);
  if (cloudFileSystemEntry == null && bThrowException)
  {
    throw new SharpBoxException(SharpBoxErrorCodes.ErrorFileNotFound);
  }
  return cloudFileSystemEntry;
}

这反过来又要求RefreshResource收藏。看起来像这样(假设了保管箱实现):

// AppLimit.CloudComputing.SharpBox.StorageProvider.BaseObjects.BaseDirectoryEntry
private void RefreshResource()
{
    this._service.RefreshResource(this._session, this);
    this._subDirectoriesRefreshedInitially = true;
}

// AppLimit.CloudComputing.SharpBox.StorageProvider.DropBox.Logic.DropBoxStorageProviderService
public override void RefreshResource(IStorageProviderSession session, ICloudFileSystemEntry resource)
{
    string resourceUrlInternal = this.GetResourceUrlInternal(session, resource);
    int num;
    string text = DropBoxRequestParser.RequestResourceByUrl(resourceUrlInternal, this, session, out num);
    if (text.Length == 0)
    {
        throw new SharpBoxException(SharpBoxErrorCodes.ErrorCouldNotRetrieveDirectoryList);
    }
    DropBoxRequestParser.UpdateObjectFromJsonString(text, resource as BaseFileEntry, this, session);
}

现在,这会调用UpdateObjectFromJsonString(我不打算粘贴到这里,因为它很大),但这似乎更新了属于集合的resource对象。因此,您的收藏会发生变化...和你的例外。

我建议你将源代码下载到SharpBox或使用IlSpy反汇编二进制文件,如果你对到底发生了什么感兴趣。但简而言之,如果您以这种方式下载文件,它将修改集合。

也许使用不会在整个集合中传递的其他DownloadFile重载之一。

不确定问题是否已解决,但根据我的经验,集合修改需要您将 IEnumerable 对象投射到 ToList() 中,这样它就不会急切地加载。