At first, I will comment points 1 and 2:
The ProblemDetected
event is raised during any Download
method, not only the one with two parameters overload.
It is limitation of our documentation system. We had to either specify cref
to one of the overloads or not use cref
at all. We decided to use cref
of the shortest overload.
If the error causes the Ftp
object to be unusable anymore, there is no need to raise ProblemDetected
event and the exception is thrown immediately.
The ProblemDetected
event is designed to solve the problem of the current file so the whole process can continue. If the Ftp
object is unusable (e.g. connection is lost) the event has no meaning.
Now, to your "Timeout exceeded" errors:
You can increase the timeout value by Ftp.Timeout
property. However, I don't think it will solve your problem (but you can try).
I think, that the problem is at the server side. The FTP protocol uses two connections: control and data. Control connection is used for commands, data connection is used for sending data of files.
When a long file is transferred, there is no communication on the control connection and this will cause the timeout at the server side.
To keep the control connection alive, set the Ftp.Settings.KeepAliveDuringTransfer
to true. Alternatively change the interval like this Ftp.Settings.KeepAliveDuringTransferInterval = 45;
If this doesn't help, please send us communication log for analysis to support@rebex.net, we hopefully spot something. You can create it as described here.
And finally, to your question:
To resume previously aborted transfer, you can use ActionOnExistingFiles.ResumeIfPossible
value as last parameter of the Upload
method. However, this will not work as expected in your case.
You are calling the Upload
method for the first time with ActionOnExistingFiles.OverwriteAll
. This means, replace content of all existing files. The ResumeIfPossible
works this way:
- if a file doesn't exist on target, upload whole file
- if a file exists on target and has smaller length than the original file, upload only remaining part
- if a file exists on target and has length equal or larger than the original file, do nothing (skip the file)
However, you would like to do something little bit different:
- skip successfully transferred files
- resume aborted file
- overwrite all remaining files
This can be done, but you have to remember, which files you already transferred.
With a little effort you can do it like this:
// holds progress of the transfer
var progress = new Dictionary<string, bool>();
// initialize client object
var client = new Rebex.Net.Ftp();
// updates progress dictionary
client.TransferProgressChanged += (s, e) =>
{
switch (e.TransferState)
{
case TransferProgressState.FileTransferring:
if (!progress.ContainsKey(e.TargetPath))
progress[e.TargetPath] = false; // uncompleted file
break;
case TransferProgressState.FileTransferred:
progress[e.TargetPath] = true; // completed file
break;
}
};
// solves problems of existing files
client.ProblemDetected += (s, e) =>
{
// handle only FileExists problems
if (e.ProblemType == TransferProblemType.FileExists)
{
bool state;
// determine target path
string targetPath = (e.Action == TransferAction.Uploading) ? e.RemotePath : e.LocalPath;
if (progress.TryGetValue(targetPath, out state))
{
if (state)
e.Skip(); // completed file
else if (e.IsReactionPossible(TransferProblemReaction.Resume))
e.Resume(); // uncompleted file
else
e.Overwrite(); // suspicious for skip, but rather overwrite
}
else
{
e.Overwrite(); // unknown file
}
}
};
With this, your try…catch…retry
construct will work as expected.