コード例 #1
0
        /// <summary>
        /// Transfers a file from the source FTP Server to the destination FTP Server via the FXP protocol
        /// </summary>
        private bool TransferFileFXPInternal(string sourcePath, FtpClient remoteClient, string remotePath, bool createRemoteDir, FtpRemoteExists existsMode,
                                             Action <FtpProgress> progress, FtpProgress metaProgress)
        {
            FtpReply reply;
            long     offset     = 0;
            bool     fileExists = false;
            long     fileSize   = 0;

            var ftpFxpSession = OpenPassiveFXPConnection(remoteClient, progress != null);

            if (ftpFxpSession != null)
            {
                try {
                    ftpFxpSession.SourceServer.ReadTimeout = (int)TimeSpan.FromMinutes(30.0).TotalMilliseconds;
                    ftpFxpSession.TargetServer.ReadTimeout = (int)TimeSpan.FromMinutes(30.0).TotalMilliseconds;


                    // check if the file exists, and skip, overwrite or append
                    if (existsMode == FtpRemoteExists.AppendNoCheck)
                    {
                        offset = remoteClient.GetFileSize(remotePath);
                        if (offset == -1)
                        {
                            offset = 0;                             // start from the beginning
                        }
                    }
                    else
                    {
                        fileExists = remoteClient.FileExists(remotePath);

                        switch (existsMode)
                        {
                        case FtpRemoteExists.Skip:

                            if (fileExists)
                            {
                                LogStatus(FtpTraceLevel.Info, "Skip is selected => Destination file exists => skipping");

                                //Fix #413 - progress callback isn't called if the file has already been uploaded to the server
                                //send progress reports
                                if (progress != null)
                                {
                                    progress(new FtpProgress(100.0, 0, 0, TimeSpan.FromSeconds(0), sourcePath, remotePath, metaProgress));
                                }

                                return(true);
                            }

                            break;

                        case FtpRemoteExists.Overwrite:

                            if (fileExists)
                            {
                                remoteClient.DeleteFile(remotePath);
                            }

                            break;

                        case FtpRemoteExists.Append:

                            if (fileExists)
                            {
                                offset = remoteClient.GetFileSize(remotePath);
                                if (offset == -1)
                                {
                                    offset = 0;                                             // start from the beginning
                                }
                            }

                            break;
                        }
                    }

                    fileSize = GetFileSize(sourcePath);

                    // ensure the remote dir exists .. only if the file does not already exist!
                    if (createRemoteDir && !fileExists)
                    {
                        var dirname = remotePath.GetFtpDirectoryName();
                        if (!remoteClient.DirectoryExists(dirname))
                        {
                            remoteClient.CreateDirectory(dirname);
                        }
                    }

                    if (offset == 0 && existsMode != FtpRemoteExists.AppendNoCheck)
                    {
                        // send command to tell the source server to 'send' the file to the destination server
                        if (!(reply = ftpFxpSession.SourceServer.Execute($"RETR {sourcePath}")).Success)
                        {
                            throw new FtpCommandException(reply);
                        }

                        //Instruct destination server to store the file
                        if (!(reply = ftpFxpSession.TargetServer.Execute($"STOR {remotePath}")).Success)
                        {
                            throw new FtpCommandException(reply);
                        }
                    }
                    else
                    {
                        //tell source server to restart / resume
                        if (!(reply = ftpFxpSession.SourceServer.Execute($"REST {offset}")).Success)
                        {
                            throw new FtpCommandException(reply);
                        }

                        // send command to tell the source server to 'send' the file to the destination server
                        if (!(reply = ftpFxpSession.SourceServer.Execute($"RETR {sourcePath}")).Success)
                        {
                            throw new FtpCommandException(reply);
                        }

                        //Instruct destination server to append the file
                        if (!(reply = ftpFxpSession.TargetServer.Execute($"APPE {remotePath}")).Success)
                        {
                            throw new FtpCommandException(reply);
                        }
                    }

                    var  transferStarted = DateTime.Now;
                    long lastSize        = 0;

                    var sourceFXPTransferReply      = ftpFxpSession.SourceServer.GetReply();
                    var destinationFXPTransferReply = ftpFxpSession.TargetServer.GetReply();

                    // while the transfer is not complete
                    while (!sourceFXPTransferReply.Success || !destinationFXPTransferReply.Success)
                    {
                        // send progress reports every 1 second
                        if (ftpFxpSession.ProgressServer != null)
                        {
                            // send progress reports
                            if (progress != null && fileSize != -1)
                            {
                                offset = ftpFxpSession.ProgressServer.GetFileSize(remotePath);

                                if (offset != -1 && lastSize <= offset)
                                {
                                    long bytesProcessed = offset - lastSize;
                                    lastSize = offset;
                                    ReportProgress(progress, fileSize, offset, bytesProcessed, DateTime.Now - transferStarted, sourcePath, remotePath, metaProgress);
                                }
                            }
                        }
#if CORE14
                        Task.Delay(FXPProgressInterval);
#else
                        Thread.Sleep(FXPProgressInterval);
#endif
                    }

                    FtpTrace.WriteLine(FtpTraceLevel.Info, $"FXP transfer of file {sourcePath} has completed");

                    Noop();
                    remoteClient.Noop();

                    ftpFxpSession.Dispose();

                    return(true);
                }

                // Fix: catch all exceptions and dispose off the FTP clients if one occurs
                catch (Exception ex) {
                    ftpFxpSession.Dispose();
                    throw ex;
                }
            }
            else
            {
                FtpTrace.WriteLine(FtpTraceLevel.Error, "Failed to open FXP passive Connection");
                return(false);
            }
        }