Пример #1
0
        private bool DeleteFtpDirectory(FtpPath path)
        {
            Log(path.Depth, ItemAction.Delete, path.Name);
            var parentWorkingDirectory = _remoteWorkingDirectory;
            var itemsRemain            = false;

            foreach (var child in _mainClient.GetListing(path.Name, FtpListOption.AllFiles))
            {
                var childPath = path.GetChildPath(child.Name);
                var exclude   = MatchExcludes(childPath.Relative);
                if (exclude != null)
                {
                    Log(path.Depth + 1, ItemAction.Skip, child.Name, $"excluded ({exclude.Original})");
                    itemsRemain = true;
                    continue;
                }

                EnsureRemoteWorkingDirectory(path.Absolute);
                if (!DeleteFtpAny(childPath, child.Type))
                {
                    itemsRemain = true;
                }
            }
            EnsureRemoteWorkingDirectory(parentWorkingDirectory);
            if (itemsRemain)
            {
                Log(path.Depth + 1, ItemAction.Skip, $"# dir '{path.Name}' not deleted (items remain)");
                return(false);
            }
            FtpRetry.ConnectedCall(_mainClient, parentWorkingDirectory, c => c.DeleteDirectory(path.Name));
            return(true);
        }
Пример #2
0
        private void PushDirectory(LocalDirectory localDirectory, FtpPath ftpParentPath)
        {
            var ftpPath = ftpParentPath.GetChildPath(localDirectory.Name);

            FtpRetry.ConnectedCall(_mainClient, ftpParentPath.Absolute, c => c.CreateDirectory(localDirectory.Name));
            PushDirectoryContents(localDirectory, ftpPath);
        }
Пример #3
0
 private void PushFile(LocalFile localFile, string ftpParentPath, string ftpPath, FtpClient client)
 {
     // https://github.com/hgupta9/FluentFTP/issues/46
     using (var readStream = localFile.OpenRead())
         using (var writeStream = FtpRetry.ConnectedCall(client, ftpParentPath, c => c.OpenWrite(ftpPath))) {
             readStream.CopyTo(writeStream, 256 * 1024);
         }
     FtpRetry.ConnectedCall(client, ftpParentPath, c => c.SetModifiedTime(ftpPath, localFile.LastWriteTimeUtc));
 }
Пример #4
0
        private void EnsureRemoteWorkingDirectory(string absolutePath, int?retryCount = null)
        {
            if (_remoteWorkingDirectory == absolutePath)
            {
                return;
            }

            FtpRetry.ConnectedCall(_mainClient, "/", c => c.SetWorkingDirectory(absolutePath), retryCount);
            _remoteWorkingDirectory = absolutePath;
        }
Пример #5
0
        public void SynchronizeTopLevel(FileSystemInfo local, string ftpPath)
        {
            var ftpPathObject     = new FtpPath(ftpPath.SubstringAfterLast("/"), ftpPath, "", 0);
            var remoteIsDirectory = false;

            try {
                EnsureRemoteWorkingDirectory(ftpPath, retryCount: 0);
                remoteIsDirectory = true;
            }
            catch (FtpCommandException ex) when(ex.CompletionCode == "550")
            {
            }

            var localAsDirectory = local as DirectoryInfo;

            if (!remoteIsDirectory)
            {
                if (localAsDirectory == null)
                {
                    Log(0, ItemAction.Replace, local.Name);
                    PushFile(new LocalFile((FileInfo)local, local.Name, 0), "/", ftpPath, _mainClient);
                    return;
                }

                if (!_mainClient.HasFeature(FtpCapability.MLSD))
                {
                    throw new NotSupportedException($"FTP server does not support MLST and no other way to know whether file {ftpPath} exists was implemented.");
                }

                if (_mainClient.GetObjectInfo(ftpPath) != null)
                {
                    DeleteFtpFile(ftpPathObject);
                }
                Log(0, ItemAction.Add, localAsDirectory.Name);
                FtpRetry.ConnectedCall(_mainClient, "/", c => c.CreateDirectory(localAsDirectory.Name));
                PushDirectoryContents(new LocalDirectory(localAsDirectory, "", 0), ftpPathObject);
                return;
            }

            if (localAsDirectory == null)
            {
                var remoteChild = _mainClient.GetListing(".", FtpListOption.AllFiles).FirstOrDefault(l => l.Name.Equals(local.Name, StringComparison.OrdinalIgnoreCase));
                SynchronizeFileAsync(new LocalFile((FileInfo)local, local.Name, 0), ftpPathObject, remoteChild)?.GetAwaiter().GetResult();
            }

            SynchronizeDirectory(new LocalDirectory(localAsDirectory, "", 0), ftpPathObject);
        }
Пример #6
0
        private async Task PushFileAsync(LocalFile localFile)
        {
            var remoteWorkingDirectory = _remoteWorkingDirectory;

            using (var pushLease = _backgroundPool.LeaseClient()) {
                // ReSharper disable AccessToDisposedClosure
                await Task.Run(() => {
                    try {
                        FtpRetry.ConnectedCall(pushLease.Client, "/", c => c.SetWorkingDirectory(remoteWorkingDirectory));
                        PushFile(localFile, remoteWorkingDirectory, localFile.Name, pushLease.Client);
                    }
                    catch (Exception ex) {
                        throw new Exception($"Failed to push file '{localFile.RelativePath}': {ex.Message}", ex);
                    }
                }).ConfigureAwait(false);

                // ReSharper restore AccessToDisposedClosure
            }
        }
Пример #7
0
        private static FtpClient CreateFtpClient(Uri url, NetworkCredential credentials, bool active, bool retry)
        {
            var encryptionMode = FtpEncryptionMode.None;

            if (url.Scheme.Equals("ftps", StringComparison.OrdinalIgnoreCase))
            {
                encryptionMode = FtpEncryptionMode.Explicit;
            }
            else if (!url.Scheme.Equals("ftp", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentValidationException($"URL scheme '{url.Scheme}' is not supported.");
            }

            FtpClient client = null;

            try {
                client = new FtpClient {
                    DataConnectionType = active ? FtpDataConnectionType.AutoActive : FtpDataConnectionType.AutoPassive,
                    Host           = url.Host,
                    Port           = !url.IsDefaultPort ? url.Port : 0,
                    EncryptionMode = encryptionMode,
                    Credentials    = credentials,
                    SslProtocols   = SslProtocols.Default | SslProtocols.Tls11 | SslProtocols.Tls12
                };
                if (retry)
                {
                    FtpRetry.ConnectedCall(client, "/", c => { /* ConnectedCall will call Connect() for us */ });
                }
                else
                {
                    client.Connect();
                }
                return(client);
            }
            catch (Exception) {
                client?.Dispose();
                throw;
            }
        }
Пример #8
0
        private void SynchronizeDirectory(LocalDirectory localDirectory, FtpPath ftpPath)
        {
            Log(localDirectory.Depth, ItemAction.Synchronize, localDirectory.Name);

            EnsureRemoteWorkingDirectory(ftpPath.Absolute);
            var allRemote = FtpRetry.ConnectedCall(_mainClient, ftpPath.Absolute, c => c.GetListing(".", FtpListOption.AllFiles))
                            .ToDictionary(l => l.Name, StringComparer.OrdinalIgnoreCase);
            var allRemoteFound = new HashSet <FtpListItem>();

            var pushTasks = new List <Task>();

            foreach (var local in localDirectory.EnumerateChildren())
            {
                var remote  = allRemote.GetValueOrDefault(local.Name);
                var exclude = MatchExcludes(local.RelativePath);
                if (exclude != null)
                {
                    Log(localDirectory.Depth + 1, ItemAction.Skip, local.Name, $"excluded ({exclude.Original})");
                    allRemoteFound.Add(remote);
                    continue;
                }

                EnsureRemoteWorkingDirectory(ftpPath.Absolute);

                if (remote != null)
                {
                    allRemoteFound.Add(remote);
                }

                var localAsDirectory = local as LocalDirectory;
                if (localAsDirectory != null)
                {
                    if (remote == null)
                    {
                        Log(localDirectory.Depth + 1, ItemAction.Add, localAsDirectory.Name);
                        PushDirectory(localAsDirectory, ftpPath);
                        continue;
                    }

                    if (remote.Type == FtpFileSystemObjectType.Directory)
                    {
                        SynchronizeDirectory(localAsDirectory, ftpPath.GetChildPath(remote.Name));
                        continue;
                    }

                    DeleteFtpFile(ftpPath.GetChildPath(remote.Name));
                    Log(localDirectory.Depth + 1, ItemAction.Add, localAsDirectory.Name);
                    PushDirectory(localAsDirectory, ftpPath);
                    continue;
                }

                var localAsFile = (LocalFile)local;
                var pushTask    = SynchronizeFileAsync(localAsFile, ftpPath, remote);
                if (pushTask != null)
                {
                    pushTasks.Add(pushTask);
                }
            }
            if (pushTasks.Count > 0)
            {
                Task.WaitAll(pushTasks.ToArray());
            }

            EnsureRemoteWorkingDirectory(ftpPath.Absolute);
            foreach (var missing in allRemote.Values.Except(allRemoteFound))
            {
                var missingPath = ftpPath.GetChildPath(missing.Name);
                var exclude     = MatchExcludes(missingPath.Relative);
                if (exclude != null)
                {
                    Log(localDirectory.Depth + 1, ItemAction.Skip, missing.Name, $"excluded ({exclude.Original})");
                    continue;
                }
                DeleteFtpAny(missingPath, missing.Type);
            }
        }
Пример #9
0
 private void DeleteFtpFile(FtpPath path)
 {
     Log(path.Depth, ItemAction.Delete, path.Name);
     FtpRetry.ConnectedCall(_mainClient, _remoteWorkingDirectory, c => c.DeleteFile(path.Name));
 }