所以我有一些代码可以递归地创建目录并分别下载文件夹中的文件。
以下是代码:
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:
为什么会这样?为什么我所做的只是下载文件时编辑了数组?
答案 0 :(得分:1)
您将整个集合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
。看起来像这样(假设了Dropbox实现):
// 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
重载之一,但不会传递整个集合。
答案 1 :(得分:0)
不确定问题是否已经解决,但根据我的经验,修改集合需要您将IEnumerable对象强制转换为ToList(),以便它不会急切加载。